Tarikan semua PDF dalam direktori, dengan mempertahankan struktur direktori

11

Saya mencoba membuat tarball terkompresi yang berisi semua file PDF yang ada di salah satu direktori saya. Struktur direktori perlu dipertahankan. Direktori kosong tidak diperlukan, tetapi saya benar-benar tidak peduli jika ada di sana.

Misalnya, saya memiliki direktori yang terlihat seperti ini:

dir
dir/subdir1
dir/subdir1/subsubdir1/song.mp3
dir/subdir2
dir/subdir2/subsubdir1
dir/subdir2/subsubdir1/document.pdf
dir/subdir2/subsubdir1/another-song.mp3
dir/subdir2/subsubdir1/top-ten-movies.txt
dir/subdir3
dir/subdir3/another-document.pdf

Setelah menjalankan perintah, saya ingin dir.tar.gzmengandung ini:

dir
dir/subdir2
dir/subdir2/subsubdir1
dir/subdir2/subsubdir1/document.pdf
dir/subdir3
dir/subdir3/another-document.pdf

Bisa jadi?

Matt Alexander
sumber

Jawaban:

10

Ini akan mencantumkan semua PDF:

$ find dir/ -name '*.pdf'
./dir/subdir2/subsubdir1/document.pdf
./dir/subdir3/another-document.pdf

Anda bisa xargsmengirimkannya ke untuk mendapatkannya sebagai satu baris ruang-dibatasi, dan memberi itu taruntuk membuat arsip:

$ find dir/ -name '*.pdf' | xargs tar czf dir.tar.gz

(Dengan cara ini menghilangkan direktori kosong)

Michael Mrozek
sumber
1
Itu luar biasa, terima kasih atas bantuannya. Inilah yang saya pikirkan:find docs \( -iname '*.pdf' -o -iname '*.mp3' \) -printf '"%p"\n' | xargs tar czf docs-media.tar.gz
Matt Alexander
3
@mattalexx: Hati-hati bahwa perintah ini tidak akan berfungsi jika ada nama file yang berisi spasi atau \'"(kesalahan xargs), dan tidak akan berfungsi jika ada terlalu banyak nama file (kesalahan kernel).
Gilles 'SANGAT berhenti menjadi jahat'
2
@Gilles Mengenai nama file dengan spasi dan tanda kutip tunggal, -printf '"%p"\n'bagian menangani itu (setidaknya itu untuk saya).
Matt Alexander
1
@Gilles Menarik tentang pembatasan kernel. Berapa banyak argumen yang bisa Anda miliki dalam perintah di Linux?
Matt Alexander
5
Oh, pada "tidak akan bekerja", perhatikan bahwa mode kegagalan di sini adalah jika baris perintah terlalu panjang, xargs akan membaginya, sehingga doa tar terakhir akan secara diam-diam menimpa file yang ditulis oleh doa sebelumnya .
Gilles 'SANGAT berhenti menjadi jahat'
6

Dengan bash ≥4 atau zsh dan tar GNU:

tar -czf dir.tar.gz dir/**/*.pdf

Ini mungkin tidak berfungsi jika Anda memiliki jumlah file PDF yang sangat besar dan baris perintah terlalu panjang. Maka Anda akan membutuhkan solusi berbasis pencarian yang lebih kompleks (sekali lagi, menggunakan tar GNU):

tar -cf dir.tar -T /dev/null
find dir -name '*.pdf' -exec tar -rf dir.tar {} +
gzip dir.tar

Atau (dan mudah dibawa) Anda dapat membuat arsip dengan pax .

pax -w -x ustar -s '/\.pdf$/&/' -s '/.*//' . | gzip >dir.tar.gz

Yang pertama -smengatakan untuk memasukkan semua .pdffile, tanpa mengubah nama mereka. Yang kedua -smengatakan untuk mengubah nama semua file lain menjadi nama kosong, yang sebenarnya berarti tidak memasukkannya ke dalam arsip.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
Oh ya, saya bermaksud untuk menyebutkan zsh ini **; Aku bahkan tidak menyadari bahwa bash 4 memilikinya sekarang
Michael Mrozek