Tarte alle PDFs in einem Verzeichnis und behalte die Verzeichnisstruktur bei

11

Ich versuche, einen komprimierten Tarball zu erstellen, der alle PDF-Dateien enthält, die in einem meiner Verzeichnisse vorhanden sind. Die Verzeichnisstruktur muss beibehalten werden. Leere Verzeichnisse werden nicht benötigt, aber es ist mir wirklich egal, ob sie da sind.

Angenommen, ich hätte ein Verzeichnis, das so aussieht:

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

Nach dem Ausführen des Befehls möchte ich Folgendes dir.tar.gzenthalten:

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

Möglich?

Matt Alexander
quelle

Antworten:

10

Dadurch werden alle PDFs aufgelistet:

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

Sie können das weiterleiten, xargsum es als einzelne durch Leerzeichen getrennte Zeile zu erhalten, und das eingeben, tarum das Archiv zu erstellen:

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

(Auf diese Weise werden die leeren Verzeichnisse weggelassen.)

Michael Mrozek
quelle
1
Das ist so toll, danke für die Hilfe. Folgendes habe ich mir ausgedacht:find docs \( -iname '*.pdf' -o -iname '*.mp3' \) -printf '"%p"\n' | xargs tar czf docs-media.tar.gz
Matt Alexander
3
@mattalexx: Beachten Sie, dass dieser Befehl nicht funktioniert, wenn einer der Dateinamen Leerzeichen oder enthält \'"(Fehler von xargs), und nicht funktioniert, wenn zu viele Dateinamen vorhanden sind (Fehler des Kernels).
Gilles 'SO - hör auf böse zu sein'
2
@ Gilles In Bezug auf Dateinamen mit Leerzeichen und einfachen Anführungszeichen -printf '"%p"\n'kümmert sich der Teil darum (zumindest für mich).
Matt Alexander
1
@ Gilles Interessant an der Kernel-Einschränkung. Wie viele Argumente können Sie in einem Befehl unter Linux haben?
Matt Alexander
5
Beachten Sie, dass der Fehlermodus hier lautet: Wenn die Befehlszeile zu lang ist, wird sie von xargs aufgeteilt, sodass der letzte Teeraufruf Dateien, die von früheren Aufrufen geschrieben wurden, stillschweigend überschreibt .
Gilles 'SO - hör auf böse zu sein'
6

Mit Bash ≥4 oder zsh und GNU tar:

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

Dies funktioniert möglicherweise nicht, wenn Sie eine sehr große Anzahl von PDF-Dateien haben und die Befehlszeile zu lang ist. Dann benötigen Sie eine komplexere findbasierte Lösung (ebenfalls mit GNU tar):

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

Alternativ (und portabel) können Sie das Archiv mit pax erstellen .

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

Der erste -sbesagt, dass alle .pdfDateien eingeschlossen werden sollen, ohne ihren Namen zu ändern. Die zweite -sbesagt, dass alle anderen Dateien in einen leeren Namen umbenannt werden sollen, was eigentlich bedeutet, sie nicht in das Archiv aufzunehmen.

Gilles 'SO - hör auf böse zu sein'
quelle
Oh ja, ich wollte zsh's erwähnen **; Ich wusste nicht einmal, dass Bash 4 das jetzt hatte
Michael Mrozek