hanya file tar, tidak ada direktori


16

Saya mungkin dapat menulis skrip shell untuk mencari file saja, kemudian meneruskan daftar ke tar, tapi saya bertanya-tanya apakah sudah ada fitur built-in di tar yang memungkinkan melakukan hal itu, dalam satu baris perintah?

Misalnya, saya menemukan --no-recursionsakelar, tetapi ketika saya melakukannya:

tar --no-recursion -cvf mydir.tar mydir

Ini hanya mengarsipkan nama entri dalam direktori (termasuk subdirektori!), Tetapi tidak mengarsipkan file apa pun.

Saya juga mencoba:

 tar --no-recursion -cvf mydir.tar mydir/*

Tetapi sementara file arsip saja, itu juga mengarsipkan nama - nama subdirektori.

Apakah ada cara untuk memberi tahu file tar saja, tidak ada direktori?


5
Hanya untuk memperjelas: apakah Anda ingin membuat arsip dengan struktur "datar" (yaitu semua file digabungkan dalam satu direktori)?
rozcietrzewiacz

1
Anda bisa membuat direktori baru find mydir -type f |xargs cp -t tempdirdan kemudian tar tempdir.
Kevin

@rozcietrzewiacz Ya, datar, tetapi hanya dari direktori itu, bukan dari subdirektori.
ateiob

1
OK, saya pikir saya melihat apa yang Anda coba lakukan. Bagaimana denganfind mydir -depth 1 -type f | xargs tar cf mydir.tar
Kevin

2
Ah, spasi. Gunakan find Ini exec sebagai gantinya: find mydir -maxdepth 1 -type f -exec tar cvf mydir.tar {} +. The +menempatkan semua file pada baris perintah yang sama seperti xargs.
Kevin

Jawaban:


11

Seperti yang ditunjukkan oleh camh, perintah sebelumnya memiliki masalah kecil karena diberi terlalu banyak nama file, perintah itu akan dieksekusi lebih dari sekali, dengan pemanggilan selanjutnya secara diam-diam menghapus proses sebelumnya. Karena kami tidak mengompresi juga, kami dapat menambahkan alih-alih menimpa:

find mydir -maxdepth 1 -type f -print0 | xargs -0 tar Avf mydir.tar
find mydir -maxdepth 1 -type f -exec tar Avf mydir.tar {} +

Jawaban Iocnarz ini menggunakan tar's --nulldan -Tpilihan bekerja dengan baik. Jika Anda telah cpiomenginstal, jawaban camh menggunakan itu juga baik-baik saja. Dan jika Anda memiliki zshdan tidak keberatan menggunakannya untuk suatu perintah, jawaban Gilles menggunakan bola zsh ( *(.)) tampaknya paling mudah.


Kuncinya adalah -maxdepthopsi. Jawaban akhir, berurusan dengan spasi secara tepat:

find mydir -maxdepth 1 -type f -print0 | xargs -0 tar cvf mydir.tar

Ini juga harus bekerja:

find mydir -maxdepth 1 -type f -exec tar cvf mydir.tar {} +

4
Kedua hal ini dapat menghasilkan banyak doa tar. Keduanya xargsdan finddengan +varian memiliki jumlah argumen maksimum yang dapat diteruskan ke tar. Ini akan menghasilkan doa kedua tar yang menimpa output yang pertama.
camh

2
Memperluas pada batas xargs, xargs default ke baris perintah 128KiB maksimum. Jika daftar file lebih besar, Anda mendapatkan doa kedua (atau lebih) dari perintah (tar), yang menyebabkan hilangnya data diam. Anda dapat menggunakan -xuntuk memaksa xarg gagal daripada kehilangan data, dan sementara lebih baik daripada bug kehilangan data diam, itu masih tidak ideal. Bug semacam ini sangat berbahaya karena semuanya tampak baik-baik saja pada awalnya, tetapi ketika daftar file bertambah seiring waktu, Anda mulai memicu dan mungkin tidak menyadarinya sampai Anda mencoba mengembalikan cadangan. Maka sudah terlambat.
camh

@camh Anda benar, terima kasih telah menunjukkannya; Saya telah memperbarui untuk mencerminkan itu.
Kevin

1
"Jawaban akhir" tidak benar, jika Anda menggunakan "tar c" tanpa -T Anda mungkin mendapatkan hasil parsial.
eckes

14

Bila Anda ingin menggunakan finddengan tar, cara terbaik adalah dengan menggunakan cpiobukan tar. cpiodapat menulis arsip tar dan dirancang untuk mengambil daftar file yang akan diarsipkan dari stdin.

find mydir -maxdepth 1 -type f -print0 | cpio -o -H ustar -0 > mydir.tar

Menggunakan finddan cpiomerupakan pendekatan yang lebih unix-y di mana Anda membiarkan findmelakukan pemilihan file dengan semua kekuatan yang dimilikinya, dan biarkan cpiomelakukan pengarsipan. Anda perlu mempelajari penggunaan sederhana ini cpio, karena Anda merasa mudah untuk menyelesaikan masalah yang Anda hadapi ketika mencoba tar.


Cemerlang! Saya telah menggunakan cpio di masa lalu, tetapi tidak pernah tahu opsi ustar.
Ian McGowan

2
Ini bekerja jauh lebih baik bagi saya daripada jawaban yang diterima.
Dale Anderson

1
hanya sebuah nit. the -maxdepth 1 seharusnya muncul sebelum -type f atau Anda akan mendapatkan peringatan dari beberapa penemuan
kdubs

Terima kasih @kdubs. Saya telah memperbarui jawaban yang diajukan -maxdepthsebelumnya -type.
camh

3

Saya tidak yakin saya mengerti kebutuhan Anda. Jika Anda ingin menyimpan file biasa mydirtetapi tidak di subdirektori, cara termudah adalah menggunakan zsh, di mana hanya mencocokkan file biasa adalah masalah sederhana menggunakan . kualifikasi glob :

tar cf mydir.tar mydir/*(.)

3

Anda bahkan dapat menggunakan find ... -print0dan tar ... --nulllangsung tanpa menggunakan xargssama sekali.

find . -maxdepth 1 -type f -print0 | tar cvf mydir.tar --null -T -

Dalam contoh yang diberikan, --no-recursionopsi untuk tartidak diperlukan karena hanya path file (dan bukan direktori) yang akan diteruskan dari findke tar.

Menggunakan --no-recursionopsi untuk tardalam contoh berikut, bagaimanapun, mencegah tardirektori pengarsipan ganda. findakan melakukan rekursi pohon direktori bukan taritu.

# compare
find . -print0 | tar cf mydir.tar --null -T -
tar -tf mydir.tar | nl

find . -print0 | tar cf mydir.tar --null --no-recursion -T -
tar -tf mydir.tar | nl

2

Seperti paragraf pengantar dalam man tarmengatakan (kalimat terakhir),

Penggunaan nama direktori selalu menyiratkan bahwa subdirektori di bawah ini harus dimasukkan dalam arsip.

Yang saya pahami sebagai jawaban "tidak" untuk pertanyaan Anda.


Baik menangkap, kecuali bahwa tar sekarang mencakup berbagai meachisms pengecualian (misalnya --no-recursion, --exclude-tag, dll). Saya mencari --exclude-tagyang terlihat menjanjikan tetapi tampaknya kebalikan dari apa yang saya cari.
ateiob

Saya mencoba ini dan saya melihat karakter dihapus dari nama path panjang. Menggunakan tar dengan -T dan --null sebagai camh yang diusulkan menghindari masalah ini.
Paul Brannan

1
star -c -C startdir -find . ! -type d > out.tar

Hapus -C startdirdan ganti. dengan startdirjika harus muncul di arsip.

Ini adalah metode paling efisien berdasarkan fitur libfind. Libfind juga menawarkan pemilihan pendahuluan -chown -chgrp -chmodyang mengubah stat struct di tempat dan memungkinkan untuk mengarsipkan metadata yang berbeda. Ini juga berfungsi dalam mode daftar dan ekstrak dan menghindari kebutuhan untuk mengekstrak seluruh arsip dalam banyak kasus.


Bisakah Anda menggunakan -finddalam -copymode. Sinopsis halaman manual menyarankan Anda bisa, tetapi saya belum dapat membuatnya berfungsi (ketika mencoba menjawab Bagaimana cara menyalin file yang dimodifikasi sambil mempertahankan struktur folder ) (dengan schily-2016-02-10)
Stéphane Chazelas

Saya tidak menguji ini untuk waktu yang lama. Mungkin ada bug saat ini. Halaman manual mengatakan bahwa argumen terakhir adalah direktori ekstraksi, tetapi ketika saya mencoba ini, saya mendapatkan: "Argumen path belum didukung dalam mode ekstrak". Apakah ini yang Anda dapatkan ketika mencoba?
schily

Iya. Halaman manual juga mengatakan Anda hanya dapat menemukan argumen setelah -temukan tetapi jika saya meletakkan direktori tujuan sebelum -temukan saya juga mendapatkan kesalahan
Stéphane Chazelas

Ada kode untuk mematikan kode find dalam proses ekstrak dan pesan kesalahan berasal dari cek yang salah yang mengharapkan -c tetapi juga harus mengizinkan-copy. Dalam mode-copy, parser find tidak boleh menyertakan argumen terakhir.
schily

1
Solusi terakhir sekarang telah diterbitkan dalam alat schily di sourceforge.net/projects/schilytools/files/schily-2016-03-11.tar.bz2 ini juga memperbaiki masalah dari setlocale () yang hilang di bintang dan ini memungkinkan - Direktori C untuk star -find.
schily

0

Saya mungkin telah menemukan solusi.

find mydir -type f -printf '%P\0'|tar czvf mydir.tar.gz -C mydir --null -T -

Ini mungkin sedikit mahal, tetapi bagaimanapun itu akan berhasil, karena ini tidak tergantung pada xargs.


-1

dir = your_dir; cd $ dir; tar -cvf file.tar `find. -maxdepth 1 -type f -print`

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.