find -exec + vs. find | xargs: Welches soll ich wählen?

find -exec + vs. find | xargs: Welches soll ich wählen?

Ich verstehe, dass Sie -execeine Option wählen können +, um das Verhalten von nachzuahmen xargs. Gibt es eine Situation, in der Sie eine Form der anderen vorziehen würden?

Ich persönlich bevorzuge die erste Form, schon allein, um die Verwendung eines Pipe-Zeichens zu vermeiden. Ich gehe davon aus, dass die Entwickler von finddie entsprechenden Optimierungen vorgenommen haben müssen. Habe ich Recht?

Antwort1

Um Dateinamen sicher an weiterzuleiten, xargsmuss Ihr finddie Option unterstützen -print0und Ihr xargsdie entsprechende Option zum Lesen ( --nulloder -0) haben. Andernfalls können Dateinamen mit nicht druckbaren Zeichen oder Backslashs oder Anführungszeichen oder Leerzeichen im Namen zu unerwartetem Verhalten führen. Andererseits find -exec {} +ist in derPOSIX find-Spezifikation, es ist also portabel und ungefähr so ​​sicher wie find -print0 | xargs -0und auf jeden Fall sicherer als find | xargs. Ich würde empfehlenniemalsverzichten .find | xargs-print0

Antwort2

Möglicherweise möchten Sie Aufrufe an find verketten (einmal, als Sie erfuhren, dass dies möglich ist, was heute der Fall sein könnte). Dies ist natürlich nur möglich, solange Sie in find bleiben. Sobald Sie an xargs weiterleiten, liegt es außerhalb des Gültigkeitsbereichs.

Kleines Beispiel, zwei Dateien a.lst und b.lst:

cat a.lst
fuddel.sh
fiddel.sh

cat b.lst
fuddel.sh

Hier gibt es keinen Trick – einfach die Tatsache, dass beide „fuddel“ enthalten, aber nur eines „fiddel“ enthält.

Angenommen, wir wussten das nicht. Wir suchen nach einer Datei, die zwei Bedingungen erfüllt:

find -exec grep -q fuddel {} ";" -exec grep -q fiddel {} ";" -ls
192097    4 -rw-r--r--   1 stefan   stefan         20 Jun 27 17:05 ./a.lst

Nun, vielleicht kennen Sie die Syntax für grep oder ein anderes Programm, um beide Zeichenfolgen als Bedingung zu übergeben, aber darum geht es nicht. Jedes Programm, das bei einer Datei als Argument true oder false zurückgeben kann, kann hier verwendet werden - grep war nur ein beliebtes Beispiel.

Und beachten Sie, Sie können folgenfinde -execmit anderen Suchbefehlen, wie-lsoder-löschenoder etwas Ähnliches. Beachten Sie, dass „delete“ nicht nur „rm“ (Dateien löschen), sondern auch „rmdir“ (Verzeichnisse löschen) ausführt.

Eine solche Kette wird als UND-Kombination von Befehlen gelesen, sofern nicht anders angegeben (nämlich mit einem -orSchalter (und Klammern (die maskiert werden müssen))).

Sie verlassen also die Suchkette nicht, was praktisch ist. Ich sehe keinen Vorteil in der Verwendung von -xargs, da Sie beim Übergeben der Dateien vorsichtig sein müssen, was find nicht tun muss - es übergibt automatisch jede Datei als einzelnes Argument für Sie.

Wenn Sie glauben, dass Sie eine Maskierung für Funde benötigen{} Zahnspange, schauen Sie sich gerne meine Frage an, in der ich nach Beweisen frage. Meine Behauptung ist: Das tun Sie nicht.

Antwort3

Wenn Sie das -exec ... ;Formular verwenden (denken Sie daran, das Semikolon zu maskieren), führen Sie den Befehl einmal pro Dateiname aus. Wenn Sie verwenden -print0 | xargs -0, führen Sie mehrere Befehle pro Dateiname aus. Sie sollten auf jeden Fall das -exec +Formular verwenden, das mehrere Dateien in eine einzige Befehlszeile einfügt und bei einer großen Anzahl von Dateien viel schneller ist.

Ein großer Vorteil von xargsist die Möglichkeit, mehrere Befehle parallel auszuführen xargs -P. Auf Multi-Core-Systemen kann das enorme Zeiteinsparungen bringen.

Antwort4

In Bezug auf die Leistung dachte ich, dass das -exec … +einfach besser wäre, weil es ein einziges Tool ist, das die ganze Arbeit erledigt, aberein Teil der Dokumentation von GNU findutilsagt, dass dies -exec … +in manchen Fällen weniger effizient sein könnte:

[finden mit -exec … +]kann weniger effizient sein als einige Verwendungen von xargs; ermöglicht beispielsweise xargsden Aufbau neuer Befehlszeilen, während der vorherige Befehl noch ausgeführt wird, und ermöglicht Ihnen die Angabe einer Anzahl parallel auszuführender Befehle. Die find ... -exec ... +Konstruktion hat jedoch den Vorteil der breiten Portabilität. GNU findutils unterstützte ' -exec ... +' erst ab Version 4.2.12[Januar 2005]; einer der Gründe dafür ist, dass die -print0Aktion „ “ ohnehin schon vorhanden war.

Ich war mir nicht ganz sicher, was das bedeutete, also fragte ich im Chat, woderoberterklärte es wie folgt:

findkönnte wahrscheinlich weiter nach dem nächsten Stapel von Dateien suchen, während der -exec … +läuft, tut es aber nicht.
find … | xargs …tut es, weil dann die Suche ein anderer Prozess ist und weiterläuft, bis der Pipe-Puffer voll ist

(Formatierung von mir.)

Das ist also so. Aber wenn es wirklich auf die Leistung ankommt, müssen Sie realistische Benchmarks durchführen oder sich sogar fragen, ob Sie in solchen Fällen überhaupt Shell verwenden möchten.

Hier auf dieser Site halte ich es für besser, den Leuten zu raten, -exec … +wann immer möglich das Formular zu verwenden, einfach weil es einfacher ist und aus den in den anderen Antworten hier genannten Gründen (z. B. Handhabung seltsamer Dateinamen ohne viel Nachdenken).

verwandte Informationen