Der Befehl find gibt Folgendes aus:
[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
Nach der Kombination mit tar wird folgende Ausgabe angezeigt:
[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
Beim Auflisten einer TAR-Datei wird jedoch nur eine einzige Datei angezeigt
[root @ localhost /] # tar -tvf file.tar -rw ------- root / root 208454 27.02.2012 12:01 var / log / anaconda.storage.log
Was mache ich hier falsch?
Mit xargs erhalte ich diese Ausgabe:
[root @ localhost /] # find var / log / -iname anaconda. * | xargs tar -cvf file1.tar
Zweite Frage
Wenn Sie / vor var eingeben , bedeutet dies, find /var/log
warum es diesen Mesaage- Teer ausgibt : Führendes `/ 'aus den Mitgliedsnamen entfernen
[root @ localhost /] # find / var / log / -iname anaconda. * -exec tar -cvf file.tar {} \; tar: Führendes `/ 'aus Mitgliedsnamen entfernen /var/log/anaconda.log tar: Führendes `/ 'aus Mitgliedsnamen entfernen /var/log/anaconda.xlog tar: Führendes `/ 'aus Mitgliedsnamen entfernen /var/log/anaconda.yum.log tar: Führendes `/ 'aus Mitgliedsnamen entfernen /var/log/anaconda.syslog tar: Führendes `/ 'aus Mitgliedsnamen entfernen /var/log/anaconda.program.log tar: Führendes `/ 'aus Mitgliedsnamen entfernen /var/log/anaconda.storage.log
Was ist in einer einfachen Form der Unterschied zwischen den folgenden beiden?
find var/log
und find /var/log
find
sollten Sie den Suchbegriff angeben. Es funktioniert ohne manchmal aber nicht immer.{} +
stattdessen verwenden{} \;
, werden die Ergebnisse von find in einem Argument zusammengefasstAntworten:
Hinweis: Siehe @ Iain Antwort für eine etwas effizientere Lösung.
Beachten Sie, dass
find
die-exec
Aktion für jede einzelne gefundene Datei aufgerufen wird .Wenn Sie
tar -cvf file.tar {}
für jede einzelne Dateiausgabe ausführenfind
, bedeutet dies, dass Sie siefile.tar
jedes Mal überschreiben. Dies erklärt, warum Sie nur noch ein Archiv haben, das nur noch enthältanaconda.storage.log
- es ist die letzte Dateiausgabefind
.Jetzt möchten Sie die Dateien tatsächlich an das Archiv anhängen , anstatt sie jedes Mal zu erstellen (dies ist die
-c
Option). Verwenden Sie also Folgendes:Die
-r
Option wird an das Archiv angehängt, anstatt es jedes Mal neu zu erstellen.Hinweis: Ersetzen Sie
-iname anaconda.*
durch-iname "anaconda.*"
. Das Sternchen ist ein Platzhalter und kann von Ihrer Shell erweitert werden, bevor esfind
überhaupt angezeigt wird. Um diese Erweiterung zu verhindern, setzen Sie das Argument in doppelte Anführungszeichen.Zum
tar
Entfernen von führenden/
: Das Archiv sollte nur relative Dateinamen enthalten . Wenn Sie Dateien mit einem vorangestellten Punkt hinzugefügt haben/
, werden diese als absolute Dateinamen gespeichert , was/var/…
beispielsweise wörtlich auf Ihrem Computer bedeutet .IIRC Dies ist lediglich eine Vorsichtsmaßnahme für
tar
andere Implementierungen als GNU, und es ist auf diese Weise sicherer, da Sie Ihre tatsächlichen Daten nicht überschreiben,/var/…
wenn Sie das Archiv extrahieren, wenn es relative Dateinamen enthält.quelle
tar
auf diese Weise ein tatsächliches Bandarchiv zu erstellen, indem Sie jeweils eine Datei hinzufügen, das Band zurückspulen und dann jedes Mal das Ganze erneut lesen, um zum Ende zu gelangen, das Ganze lächerlich langsam wäre. Ihre Lösung ist nur geeignet, wenn Sie die tar-Datei auf die Festplatte schreiben.find /var/log/ -iname anaconda*
nichts geben undfind /var/log/ -iname anaconda.*
die Ausgabe geben, warum?find
. Also , wenn Sieanaconda*
, und im aktuellen Ordner gibt es etwas namens zum Beispielanaconda5
(für diese Wildcard), wird der Platzhalter erweitert undfind
werden sehen ,-iname anaconda5
statt-iname anaconda*
. Warum das erste nicht funktioniert und das zweite, hängt davon ab, welche Dateien sich in Ihrem aktuellen Verzeichnis befinden. @max{} +
anstelle von verwenden,{} \;
damit die Ergebnisse der Suche in einem Argument zusammengefasst werdenSie können Folgendes verwenden:
Das
-print0
und-T
arbeiten zusammen, um Dateinamen mit Leerzeichen, Zeilenumbrüchen usw. zuzulassen. Das letzte-
weist tar an, die eingegebenen Dateinamen von stdin zu lesen.Beachten Sie, dass diese Antwort
-print0
am Ende Ihrer Aussage stehen muss . Andernfalls erhalten Sie wahrscheinlich mehr Dateien als erwartet.quelle
-name
Option weggelassen und die Lösung fürtar
das gesamte Verzeichnis erstellt. Wenn das , was Sie wollen, können Sie es tun leichter alstar -cvf file.tar var/log
ohnefind
überhaupt.tar
ist eine gute Idee. Es ist definitiv die beste Lösung, wenn Sie erwarten, dass die Pfadnamen Leerzeichen enthalten. Ich würde es sogar als das technisch beste bezeichnen, da es sowohl zuverlässig als auch effizient ist. Es sind jedoch zusätzliche Spezialkenntnisse in beidenfind
und erforderlichtar
. Ich bevorzuge die Befehlsersetzung so ziemlich nur, weil es ein allgemeineres Werkzeug ist: Lerne, wie man es einmal benutzt und benutze es dann überall. (Aber ich gebe zu, ich bin auf Windows mit einer Shell, wo es immer funktioniert.) Entschuldigung, wenn ich unhöflich schien.xargs
.-print0
Option find verwenden , benötigen Sie auch die--null
Option tar .--no-unquote
stellt sich heraus, dass dies ebenfalls erforderlich ist: Dateinamen, die Backslashes enthalten, würden ansonsten falsch behandelt. (Nein, das ist keine Hypothese - ich erstelle wirklich ein Tar-Archiv aus dem Code einer anderen Person, das einen Dateinamen mit Backslashes im Namen enthält. So habe ich es herausgefunden.)Versuche dies:
Sie versuchen , zu verwenden ,
find
zu-exec tar
. Bei der Funktionsweise der-exec
Option wird dieser Befehl jedoch für jede gefundene übereinstimmende Datei einmal ausgeführt, wodurch dietar
von ihr erzeugte TAR-Datei jedes Mal überschrieben wird. Deswegen bist du nur beim letzten gelandet. Außerdem müssen Sie das angegebene Muster in Anführungszeichen setzen,find
damit die Shell es nicht erweitert, bevor Sie es an übergebenfind
.Wenn Sie die Befehlsersetzung mit Backticks verwenden (oder die
$(...)
Notation verwenden, wenn Sie dies vorziehen), wird die gesamte Liste der Namen, die von erzeugt wurdenfind
, als Argumente in die Befehlszeile eingefügttar
, sodass alle auf einmal geschrieben werden.quelle
find
ist selten eine gute Idee. mywiki.wooledge.org/ParsingLsread -r
von-print0
) verwenden, wie ich es in meiner Antwort getan habe.Frage 1
Ihr Befehl schlägt fehl, weil
tar
alle gefundenen Dateien übernommen und archiviert werdenfile.tar
. Jedes Mal, wenn dies der Fall ist, wird der zuvor erstellte Wert überschriebenfile.tar
.Wenn Sie nur ein Archiv mit allen Dateien haben möchten, führen Sie es einfach
tar
direkt aus, es ist nicht erforderlichfind
(und ja, dies funktioniert für Dateien mit Leerzeichen im Namen):Frage 2
Die beiden Befehle sind völlig unterschiedlich:
find var / log durchsucht ein Verzeichnis mit dem Namen,
var/log
das ein Unterverzeichnis Ihres aktuellen Verzeichnisses istfind ./var/log
(beachten Sie das./
).find / var / log durchsucht ein Verzeichnis mit dem Namen,
/var/log
das ein Unterverzeichnis des Stammverzeichnisses ist/
.Die
/
Leitbotschaft kommt vontar
, nichtfind
. Dies bedeutet, dass der erste/
Ihrer Dateinamen entfernt wird, um absolute Pfade zu relativen Pfaden zu machen . Dies bedeutet, dass die Datei von/var/log/anaconda.error
nach extrahiert wird,./var/log/anaconda.error
wenn Sie das Archiv entpacken.quelle
Es gibt zwei Möglichkeiten,
-exec
die funktionieren können. Auf eine Weise wird der Befehl mehrmals ausgeführt - einmal für jede Datei. Auf die andere Weise wird der Befehl einmal ausgeführt, einschließlich aller Dateien als Parameterliste.-exec tar -cvf file.tar {} ';'
Führt dentar
Befehl für jede Datei aus und überschreibt das Archiv jedes Mal.-exec tar -cvf file.tar {} '+'
Führt dentar
Befehl einmal aus und erstellt ein Archiv aller gefundenen Dateien.quelle
Ich denke, die Verwendung von -exec für jede Datei kann die Tar-Komprimierung sehr langsam machen, wenn Sie viele Dateien haben. Ich bevorzuge den Befehl:
quelle
/bin/cpio: xxx: Cannot open: Too many open files