Wie werden bestimmte Dateitypen in allen Unterverzeichnissen tariert?

85

Ich möchte tar und alle .php- und .html-Dateien in einem Verzeichnis und seinen Unterverzeichnissen speichern. Wenn ich benutze

tar -cf my_archive *

Es tariert alle Dateien, die ich nicht will. Wenn ich benutze

tar -cf my_archive *.php *.html

Unterverzeichnisse werden ignoriert. Wie kann ich es rekursiv tarieren lassen, aber nur zwei Dateitypen einschließen?

user1566515
quelle

Antworten:

145

find ./someDir -name "*.php" -o -name "*.html" | tar -cf my_archive -T -

DeeDee
quelle
@DeeDee Gibt es Einschränkungen hinsichtlich der Anzahl der Dateien usw.?
user1566515
1
@DeeDee - nein, ich meinte, du brauchst die Parens nicht!
Mike Makuch
@ user1566515 Möglicherweise gibt es eine Dateisystembeschränkung oder eine allgemeine Speicherplatzbeschränkung, die eine Obergrenze für Ihre TAR-Datei festlegen würde. Das hängt ganz von Ihrem eigenen System ab. Andernfalls wird die TAR-Datei im Wesentlichen im laufenden Betrieb erstellt, sodass Sie nicht durch die Dateinummer oder -größe eingeschränkt werden.
DeeDee
Vielen Dank! ... wie man mehr als 2 Bedingungen / Dateityp hinzufügt?
Gluuke
5
@ Gluuke verwenden -o -name [pattern]für jede neue Bedingung
DeeDee
15

Wenn Sie bashVersion> 4.0 verwenden, können Sie Folgendes ausnutzen shopt -s globstar, um Folgendes zu erledigen:

shopt -s globstar; tar -czvf deploy.tar.gz **/Alice*.yml **/Bob*.json

Dadurch werden alle .yml-Dateien, die mit Alice beginnen, aus einem beliebigen Unterverzeichnis hinzugefügt und alle .json-Dateien, die mit Bob beginnen, aus einem beliebigen Unterverzeichnis hinzugefügt.

Sairam Krish
quelle
2
Die einzige Antwort, die nur Teer verwendet, die beste Antwort IMO.
Simon
2
Trotz des Eindrucks von glob '**' für Verzeichnis wird dieser Befehl nicht rekursiv ausgeführt (keine Unter-Unterordner)
Eddie
@ Eddie ** sollte funktionieren. Möglicherweise gibt es etwas anderes mit Ihren Parametern. Überprüfen Sie auch, ob im Ordnernamen ein Leerzeichen vorhanden ist, das Sie in der Befehlszeile übergeben. Wenn nicht, können Sie Ihren eigentlichen Befehl einfügen?
Sairam Krish
'**' wird von der Shell vor Erreichen des Befehls ausgewertet und nur als 2 unabhängige * angesehen, die in 0 oder Zeichen aufgelöst werden. Es hat keine rekursive Funktionalität, um Verzeichnisse zu überspannen. Tldp.org/LDP/GNU-Linux-Tools-Summary/ html / x11655.htm
Eddie
2
@eddie ja es wird von Shell ausgewertet, obwohl Bash> 4.0 eine shopt -s globstarOption hat, so dass die Antwort korrekt ist und tatsächlich die beste ist
Roman Usherenko
13

Eine Methode ist:

tar -cf my_archive.tar $( find -name "*.php" -or -name "*.html" )

Bei dieser Methode gibt es jedoch einige Einschränkungen:

  1. Es schlägt fehl, wenn Dateien oder Verzeichnisse mit Leerzeichen darin enthalten sind, und
  2. Es schlägt fehl, wenn so viele Dateien vorhanden sind, dass die maximale Befehlszeilenlänge voll ist.

Eine Problemumgehung könnte darin bestehen, den Inhalt des Befehls find in eine Datei auszugeben und dann die Option "-T, --files-from FILE" zum Tarieren zu verwenden.

Robin Sheat
quelle
1) Mit "fehlschlagen" meinen Sie, dass die Dateien mit Leerzeichen übersprungen werden oder das Teerarchiv nicht erstellt wird? 2) Ich habe ungefähr 100K Dateien. Liegt das über der maximalen Befehlszeilenlänge?
user1566515
1
1. Das Archiv wird erstellt, es werden jedoch fehlende Dateien gemeldet. 2. Das wird wohl zu lange dauern. In Anbetracht dessen ist es am besten, eine Methode zu verwenden, wie sie @DeeDee unten vorschlägt. Sie wird diese Probleme recht gut umgehen.
Robin Sheat
3

Dies behandelt Pfade mit Leerzeichen:

find ./ -type f -name "*.php" -o -name "*.html" -exec tar uvf myarchives.tar {} +
Ian Reinhart Geiser
quelle
0

Legen Sie sie in eine Datei

find . \( -name "*.php" -o -name "*.html" \) -print > files.txt

Verwenden Sie dann die Datei als Eingabe für tar, verwenden Sie -I oder -T, je nachdem, welche Version von tar Sie verwenden

Verwenden Sie h, um symbolische Links zu kopieren

tar cfh my.tar -I files.txt 
Noam Geffen
quelle
0

find ./ -type f -name "*.php" -o -name "*.html" -printf '%P\n' |xargs tar -I 'pigz -9' -cf target.tgz

für Multicore oder nur für einen Kern:

find ./ -type f -name "*.php" -o -name "*.html" -printf '%P\n' |xargs tar -czf target.tgz

dmitry_podyachev
quelle
-2
tar -cf my_archive `find ./ | grep '.php\|.html'`

Verwenden Sie "find" und "grep", um den gesamten Pfad der .php- und .html-Dateien in allen Verzeichnissen und deren Unterverzeichnissen abzurufen. Übergeben Sie diese Pfadinformationen dann an tar, um sie zu komprimieren.

Bitte seien Sie vorsichtig mit den Symbolen "und". Beachten Sie auch, dass dies im Gegensatz zu einigen anderen Antworten die Grenze für die Anzahl der Zeichen überschreitet, die Ihre Shell in der Befehlszeile zulässt.

Trent Huang
quelle