Perintah find memberikan output ini:
[root @ localhost /] # find var / log / -iname anaconda. * var / log / anaconda.log var / log / anaconda.xlog var / log / anaconda.yum.log var / log / anaconda.syslog var / log / anaconda.program.log var / log / anaconda.storage.log
Setelah digabungkan dengan tar, ia menampilkan output ini:
[root @ localhost /] # find var / log / -iname anaconda. * -exec tar -cvf file.tar {} \; var / log / anaconda.log var / log / anaconda.xlog var / log / anaconda.yum.log var / log / anaconda.syslog var / log / anaconda.program.log var / log / anaconda.storage.log
Tetapi sementara daftar file tar itu hanya menampilkan satu file
[root @ localhost /] # tar -tvf file.tar -rw ------- root / root 208454 2012-02-27 12:01 var / log / anaconda.storage.log
Apa yang saya lakukan salah di sini?
Dengan xargs saya mendapatkan output ini:
[root @ localhost /] # find var / log / -iname anaconda. * | xargs tar -cvf file1.tar
Pertanyaan kedua
Saat mengetik / di depan var, berarti find /var/log
mengapa ini memberikan tar mesaage ini : Menghapus awalan `/ 'dari nama anggota
[root @ localhost /] # find / var / log / -iname anaconda. * -exec tar -cvf file.tar {} \; tar: Menghapus awalan `/ 'dari nama anggota /var/log/anaconda.log tar: Menghapus awalan `/ 'dari nama anggota /var/log/anaconda.xlog tar: Menghapus awalan `/ 'dari nama anggota /var/log/anaconda.yum.log tar: Menghapus awalan `/ 'dari nama anggota /var/log/anaconda.syslog tar: Menghapus awalan `/ 'dari nama anggota /var/log/anaconda.program.log tar: Menghapus awalan `/ 'dari nama anggota /var/log/anaconda.storage.log
Dalam bentuk sederhana apa perbedaan antara dua berikut?
find var/log
dan find /var/log
find
perintah, Anda harus mengutip istilah pencarian. Kadang-kadang berfungsi tanpa tetapi tidak selalu.{} +
sebagai gantinya{} \;
akan mengelompokkan hasil temuan ke dalam satu argumenJawaban:
Catatan: Lihat jawaban @ Iain untuk solusi yang agak lebih efisien.
Catatan yang
find
akan memanggil-exec
tindakan untuk setiap file yang ditemukannya.Jika Anda menjalankan
tar -cvf file.tar {}
untuk setiapfind
output file tunggal , ini berarti Anda akan menimpafile.tar
setiap waktu, yang menjelaskan mengapa Anda berakhir dengan satu arsip tersisa yang hanya berisianaconda.storage.log
- itu adalahfind
output file terakhir .Sekarang, Anda sebenarnya ingin menambahkan file ke arsip alih-alih membuatnya setiap kali (inilah yang dilakukan
-c
opsi). Jadi, gunakan yang berikut ini:The
-r
pilihan menambahkan ke arsip bukannya menciptakan itu setiap kali.Catatan: Ganti
-iname anaconda.*
dengan-iname "anaconda.*"
. Tanda bintang adalah wildcard dan dapat diperluas oleh shell Andafind
bahkan sebelum melihatnya. Untuk mencegah ekspansi ini, bungkus argumen dalam tanda kutip ganda.Adapun
tar
menghapus memimpin/
: Arsip hanya boleh berisi nama file relatif . Jika Anda menambahkan file dengan informasi utama/
, mereka akan disimpan sebagai nama file absolut , artinya secara harfiah/var/…
di komputer Anda, misalnya.IIRC ini hanyalah tindakan pencegahan untuk
tar
implementasi selain GNU, dan ini lebih aman dengan cara ini karena Anda tidak akan menimpa data aktual/var/…
saat Anda mengekstrak arsip jika berisi nama file relatif.sumber
tar
mengarsipkan kaset yang sebenarnya dengan cara ini, menambahkan satu file setiap saat, memutar ulang kaset itu, kemudian membaca ulang semuanya setiap kali untuk sampai ke akhir, semuanya akan menjadi sangat lambat. Solusi Anda hanya cocok jika Anda menulis file tar ke disk.find /var/log/ -iname anaconda*
tidak memberikan apa pun danfind /var/log/ -iname anaconda.*
memberikan hasilnya, mengapa?find
lagi. Jadi jika sudahanaconda*
, dan di folder Anda saat ini ada sesuatu yang dinamai, misalnya,anaconda5
(cocok dengan wildcard ini), wildcard akan diperluas, danfind
akan melihat-iname anaconda5
sebagai gantinya-iname anaconda*
. Mengapa yang pertama tidak berfungsi dan yang kedua tergantung pada file apa yang ada di direktori Anda saat ini. @max{} +
alih-alih{} \;
sehingga akan mengelompokkan hasil temuan ke dalam satu argumenAnda dapat menggunakan sesuatu seperti:
The
-print0
dan-T
bekerja sama untuk memungkinkan nama file dengan spasi baris baru, dll. Final-
memberitahu tar untuk membaca nama file input dari stdin.Catatan yang
-print0
harus datang di akhir pernyataan Anda, per jawaban ini . Kalau tidak, Anda mungkin akan mendapatkan lebih banyak file dari yang Anda harapkan.sumber
-name
opsi, menyebabkan solusi Anda ketar
seluruh direktori. Jika itu yang Anda inginkan, Anda bisa melakukannya dengan lebih mudahtar -cvf file.tar var/log
tanpa menggunakanfind
sama sekali.tar
adalah ide yang bagus. Ini jelas merupakan solusi terbaik jika Anda mengharapkan pathnames memiliki spasi. Saya bahkan akan menggambarkannya sebagai yang terbaik secara teknis, karena dapat diandalkan dan efisien. Tetapi membutuhkan pengetahuan khusus tambahan dari keduanyafind
dantar
. Saya lebih suka substitusi perintah hanya karena ini adalah alat yang lebih umum: Pelajari cara menggunakannya sekali, lalu gunakan di mana-mana. (Tapi saya akui, saya menggunakan Windows di shell yang selalu berfungsi.) Maaf jika saya tampak kasar.xargs
.-print0
opsi find , Anda juga membutuhkan--null
opsi tar .--no-unquote
ternyata diperlukan juga: nama file yang mengandung backslash akan dinyatakan salah penanganan. (Tidak, ini bukan hipotetis - Saya benar-benar membuat arsip tar dari kode orang lain, berisi nama file dengan backslash dalam namanya, itulah yang saya temukan.)Coba ini:
Anda mencoba menggunakannya
find
untuk-exec tar
. Tetapi cara-exec
opsi bekerja, ia menjalankan perintah itu sekali untuk setiap file yang cocok ditemukan, menyebabkantar
menimpa file tar yang dihasilkannya setiap kali. Itu sebabnya Anda hanya berakhir dengan yang terakhir. Anda juga perlu memberi tanda kutip di sekitar pola yang Anda tentukanfind
agar shell tidak memperluasnya sebelum meneruskannyafind
.Menggunakan substitusi perintah dengan backticks (atau menggunakan
$(...)
notasi jika Anda suka), seluruh daftar nama yang dihasilkan olehfind
ditempelkan kembali ke baris perintah sebagai argumentar
, menyebabkannya untuk menuliskan semuanya sekaligus.sumber
find
jarang merupakan ide yang baik. mywiki.wooledge.org/ParsingLsread -r
dari-print0
) seperti yang saya lakukan dalam jawaban saya.pertanyaan 1
Perintah Anda gagal karena
tar
mengambil setiap file yang ditemukan dan mengarsipkannyafile.tar
. Setiap kali melakukannya, itu akan menimpa yang dibuat sebelumnyafile.tar
.Jika yang Anda inginkan adalah satu arsip dengan semua file, maka jalankan saja
tar
secara langsung, tidak perlufind
(dan ya, ini berfungsi untuk file dengan spasi di namanya):Pertanyaan 2
Kedua perintah ini sangat berbeda:
find var / log akan mencari direktori yang disebut
var/log
subdirektori dari direktori Anda saat ini , itu setara denganfind ./var/log
(perhatikan./
).find / var / log akan mencari direktori yang disebut
/var/log
subdirektori dari root/
,./
Pesan utama berasal daritar
, bukanfind
. Ini berarti bahwa itu menghapus yang pertama/
dari nama file Anda untuk membuat path absolut menjadi relatif . Ini berarti bahwa file dari/var/log/anaconda.error
akan diekstraksi./var/log/anaconda.error
ketika Anda menghapus arsip.sumber
Ada dua cara yang
-exec
bisa berhasil. Satu cara menjalankan perintah berkali-kali - satu kali untuk setiap file; cara lain menjalankan perintah satu kali, termasuk semua file sebagai daftar parameter.-exec tar -cvf file.tar {} ';'
menjalankantar
perintah untuk setiap file, menimpa arsip setiap kali.-exec tar -cvf file.tar {} '+'
menjalankantar
perintah sekali, membuat arsip semua file yang ditemukan.sumber
Saya pikir menggunakan -exec untuk setiap file dapat membuat kompresi tar sangat lambat, jika Anda memiliki banyak file. Saya lebih suka menggunakan perintah:
sumber
/bin/cpio: xxx: Cannot open: Too many open files