Nur TAR-Dateien, keine Verzeichnisse

16

Ich kann wahrscheinlich ein Shell-Skript schreiben, um nur Dateien zu finden, und dann die Liste an tar übergeben, aber ich frage mich, ob es in tar bereits eine integrierte Funktion gibt, die genau dies in einer einzigen Befehlszeile ermöglicht.

Zum Beispiel fand ich den --no-recursionSchalter, aber wenn ich tun:

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

Es archiviert nur die Namen der Einträge im Verzeichnis (einschließlich Unterverzeichnisse!), Aber es archivieren keine Dateien.

Ich habe auch versucht:

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

Aber während es Archive - Dateien nur, es auch archiviert die Namen der Unterverzeichnisse.

Gibt es eine Möglichkeit nur tar-Dateien zu sagen, keine Verzeichnisse?

ateiob
quelle
5
Nur um zu klären: Haben Sie ein Archiv mit „flacher“ Struktur (dh alle Dateien gemischt in einem Verzeichnis) erstellen?
rozcietrzewiacz
1
Sie könnten ein neues Verzeichnis und erstellen find mydir -type f |xargs cp -t tempdirund dann tar tempdir.
Kevin
@rozcietrzewiacz Ja, flach, aber nur aus diesem Verzeichnis nicht aus Verzeichnissen.
ateiob
1
OK, ich glaube , ich sehe , was Sie zu tun versuchen. Wie wäre esfind mydir -depth 1 -type f | xargs tar cf mydir.tar
Kevin
2
Ah, Räume. Verwendung finden ist -exec statt: find mydir -maxdepth 1 -type f -exec tar cvf mydir.tar {} +. Das +bringt alle Dateien auf die gleiche Kommandozeile wie xargs.
Kevin

Antworten:

11

Wie camh betont, hatte der vorherige Befehl ein kleines Problem, da er bei zu vielen Dateinamen mehr als einmal ausgeführt wurde und spätere Aufrufe die vorherigen Läufe stillschweigend auslöschten. Da wir auch nicht komprimieren, können wir Folgendes anhängen, anstatt es zu überschreiben:

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

Iocnarz Antwort der Verwendung von tar‚s --nullund -TOptionen funktioniert auch. Wenn Sie cpioinstalliert haben, ist camhs Antwort auch in Ordnung. Und wenn es Ihnen zshetwas ausmacht, es für einen Befehl zu verwenden, scheint Gilles 'Antwort mit einem zsh glob ( *(.)) am einfachsten zu sein.


Der Schlüssel war die -maxdepthOption. Endgültige Antwort, mit Leerzeichen alles einer angemessenen Umgang:

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

Dies sollte auch funktionieren:

find mydir -maxdepth 1 -type f -exec tar cvf mydir.tar {} +
Kevin
quelle
4
Beides kann zu mehreren Aufrufen von führen tar. Beide xargsund findmit der +Variante hat eine maximale Anzahl von Argumenten, die an tar übergeben werden können. Dies wird in dem zweiten Aufruf von tar Ergebnis des Ausgangssignal der ersten zu überschreiben.
6.
2
Aufbauend auf der Xargs Grenze xargs Standard auf eine maximale 128KiB Befehlszeile. Wenn die Dateiliste größer ist, erhalten Sie einen zweiten (oder mehr) Aufruf des Befehls (tar), was zu einem unbeaufsichtigten Datenverlust führt. Sie können -xXargs zwingen, fehlzuschlagen, anstatt Daten zu verlieren, und obwohl dies besser ist als ein Programmfehler mit unbeaufsichtigtem Datenverlust, ist es immer noch nicht ideal. Dieser Sortierfehler ist so gefährlich, weil zunächst alles in Ordnung zu sein scheint. Wenn die Dateiliste jedoch mit der Zeit wächst, wird er möglicherweise ausgelöst und erst dann bemerkt, wenn Sie versuchen, Ihr Backup wiederherzustellen. Dann ist es zu spät.
Camh
@camh Du hast recht, danke, dass du darauf hingewiesen hast; Ich habe aktualisiert, um das zu reflektieren.
Kevin
1
Die "endgültige Antwort" ist nicht korrekt. Wenn Sie "tar c" ohne -T verwenden, erhalten Sie möglicherweise Teilergebnisse.
eckes
14

Wenn Sie verwenden möchten , findmit tar, ist der beste Weg , zu verwenden , cpiostatt tar. cpiokann tar-Archive schreiben und dient dazu, die Liste der zu archivierenden Dateien von stdin zu übernehmen.

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

Die Verwendung von findund cpioist insofern ein unix-y-Ansatz, als Sie finddie Dateiauswahl mit der gesamten Leistungsfähigkeit durchführen und cpiodie Archivierung durchführen lassen. Es lohnt sich, diese einfache Verwendung zu erlernen cpio, da Sie es leicht finden, Probleme zu lösen, gegen die Sie sich beim Versuch durchsetzen tar.

camh
quelle
Brillant! Ich habe in der fernen Vergangenheit cpio verwendet, wusste aber nie von der Option ustar.
Ian McGowan
2
Das funktionierte für mich viel besser als die akzeptierte Antwort.
Dale Anderson
3

Ich bin nicht sicher, ob ich Ihre Anforderungen verstehe. Wenn Sie die regulären Dateien in mydireinem anderen Verzeichnis als den zugehörigen Unterverzeichnissen speichern möchten , verwenden Sie am einfachsten zsh. Dabei müssen Sie nur das . Glob-Qualifikationsmerkmal verwenden, um die regulären Dateien abzugleichen :

tar cf mydir.tar mydir/*(.)
Gilles 'SO - hör auf böse zu sein'
quelle
3

Sie können sogar nutzen find ... -print0und tar ... --nulldirekt ohne xargsüberhaupt.

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

In dem angegebenen Beispiel ist die --no-recursionOption to tarnicht erforderlich, da nur Dateipfade (und keine Verzeichnisse) von findan übergeben werden tar.

Durch die Verwendung der --no-recursionOption tarin dem folgenden Beispiel wird jedoch verhindert, dass tarVerzeichnisse doppelt archiviert werden. findführt stattdessen die Verzeichnisbaum-Rekursion durch tar.

# 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
locnarz
quelle
2

Wie der einleitende Absatz in man tarsagt (letzter Satz),

Die Verwendung eines Verzeichnisnamens impliziert immer, dass die folgenden Unterverzeichnisse im Archiv enthalten sein sollten.

Was ich als eine "Nein" Antwort auf Ihre Frage verstehe.

rozcietrzewiacz
quelle
Guter Fang, mit der Ausnahme , dass Teer enthält nun zahlreiche Ausschlüsse meachisms (zB --no-recursion, --exclude-tagusw.). Ich suche, --exclude-tagwas vielversprechend aussieht, aber genau das Gegenteil von dem zu sein scheint, wonach ich suche.
Ateiob
Ich habe es versucht und gesehen, wie Zeichen aus langen Pfadnamen entfernt wurden. Die Verwendung von tar mit -T und --null, wie von camh vorgeschlagen, vermeidet dieses Problem.
Paul Brannan
1
star -c -C startdir -find . ! -type d > out.tar

Auslassen -C startdirund ersetzen .mit , startdirwenn sie im Archiv angezeigt werden sollen.

Dies ist die effizienteste Methode, die auf den Funktionen von libfind basiert. Libfind bietet auch Primärdaten an -chown -chgrp -chmod, mit denen die Strukturstatistik geändert und verschiedene Metadaten archiviert werden können. Dies funktioniert auch im Listen- und Extraktionsmodus und vermeidet in vielen Fällen die Notwendigkeit, das gesamte Archiv zu extrahieren.

schily
quelle
Kannst du -findim -copyModus verwenden. Die Manpage-Zusammenfassung schlägt vor, dass Sie es können, aber ich konnte es nicht zum Laufen bringen (beim Versuch zu antworten, wie geänderte Dateien unter Beibehaltung der Ordnerstruktur kopiert werden) (mit schily-2016-02-10)
Stéphane Chazelas
Ich habe das längere Zeit nicht getestet. Es kann sein, dass derzeit ein Fehler vorliegt. Die Manpage besagt, dass das letzte Argument das Extraktionsverzeichnis sein würde, aber wenn ich das versuche, erhalte ich: "Pfadargumente, die im Extraktionsmodus noch nicht unterstützt werden". Erhalten Sie das, wenn Sie es versuchen?
Schily
Ja. Die Manpage sagt auch, dass Sie nur nach -find nach Argumenten suchen können, aber wenn ich das Zielverzeichnis vor -find stelle, erhalte ich auch eine Fehlermeldung
Stéphane Chazelas
Es gibt Code zum Ausschalten des Suchcodes im Extrahierungsprozess und die Fehlermeldung stammt von einer falschen Prüfung, die -c erwartet, aber auch -copy zulassen sollte. Im Kopiermodus sollte der Suchparser nicht das letzte Argument enthalten.
Schily
1
Eine endgültige Lösung wurde jetzt in den schily-Tools unter sourceforge.net/projects/schilytools/files/schily-2016-03-11.tar.bz2 veröffentlicht. Dies behebt auch das Problem einer fehlenden setlocale () in star und ermöglicht Folgendes: C Verzeichnis für star -find.
Schily
0

Ich hätte vielleicht eine Lösung gefunden.

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

Dies mag ein wenig kostenintensiv sein, aber es wird trotzdem funktionieren, da dies nicht von xargs abhängt.

ciel
quelle
-1

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

H Bosch
quelle