Wie führe ich mehrere Befehle aus, wenn ich find verwende?

Wie führe ich mehrere Befehle aus, wenn ich find verwende?

Ich versuche, mehrere Befehle für Dinge auszuführen, die ich gefunden habe. Wie kann ich das erreichen?

find . -exec cmd1; cmd2

scheint nicht zu funktionieren; stattdessen wird cmd2 ausgeführt, nachdem cmd1 für jede Datei ausgeführt wurde.

Antwort1

In dieser Demonstration verwende ich sh -c 'echo first; false'(oder true) für das erste -exec. Dies gibt eine Ausgabe aus und hat auch den ausgewählten Exitcode-Effekt. Dann echo secondwird für das zweite verwendet. Nehmen wir an, dass sich im aktuellen Verzeichnis eine Datei befindet.

$ find . -type f -exec sh -c 'echo first; false' \; -exec echo second \;
first
$ find . -type f -exec sh -c 'echo first; true' \; -exec echo second \;
first
second
$ find . -type f \( -exec sh -c 'echo first; false' \; -false -o -exec echo second \; \)
first
second
$ find . -type f \( -exec sh -c 'echo first; false' \; -false -o -exec echo second \; \)
first
second

Ein echter Befehl dieser Art würde etwa so aussehen:

find . -type f \( -exec command1 \; -false -o -exec command2 \; \)

Im zweiten Satz gruppieren die Escape-Klammern die beiden -execKlauseln. Das -falsezwischen ihnen erzwingt den Testzustand „falsch“ und das -obewirkt, dass der nächste Ausdruck (der zweite -exec) aufgrund des ausgewertet wird -false.

Aus man find:

expr1 expr2
Zwei Ausdrücke in einer Zeile werden als mit einem impliziten „und“ verbunden betrachtet; expr2 wird nicht ausgewertet, wenn expr1 falsch ist.

expr1 -a expr2
Dasselbe wie expr1 expr2.

expr1 -o expr2
Oder: expr2 wird nicht ausgewertet, wenn expr1 wahr ist.

Antwort2

Wenn es Ihnen egal ist, ob cmd1 die Ausführung von cmd2 aufgrund des Fehlercodes verhindern kann 0:

find . -exec cmd1 \; -exec cmd2 \;

Die einzige zuverlässige Möglichkeit, immer beide Befehle auszuführen, besteht darin, findeine Shell aufzurufen, die die Befehle anschließend nacheinander ausführt:

find . -exec bash -c 'cmd1; cmd2' filedumper {} \;

Antwort3

Wenn es Ihnen nichts ausmacht, ein Skript zu erstellen, das cmd1 und cmd2 ausführt, dann genügt es:

find . -exec myscript {} \;

oder

find . -exec myscript {} +

Verwenden Sie \; oder +, je nachdem, ob Myscript mehr als eine Datei gleichzeitig verarbeiten kann (wird pikant, wenn Dateinamen Leerzeichen usw. enthalten).

Meiner Erfahrung nach hat es sich fast immer gelohnt, das, was Sie tun, in ein Skript zu packen. Wenn Sie es einmal tun müssen, müssen Sie es erneut tun.

Aber ein guter Trick ist, den Fundinnendas Skript:

if [ $# -gt 0 ]; then
    for each; do
        touch $each
    done
else
    find . -exec $0 {} +
fi

Dann arbeitet myscript mit allen Dateien, die Sie als Argumente angeben, aber wenn Sie ihm keine Argumente geben, führt es find aus dem aktuellen Verzeichnis aus und ruft sich dann selbst für die gefundenen Dateien auf. Dadurch wird die Tatsache umgangen, dass find -exec keine Shell-Funktionen aufrufen kann, die Sie in Ihrem Skript definiert haben.

Antwort4

Versuchen Sie den Befehl:

sudo find -name "*[!0-9][1-9].txt" -exec chmod 744 * {} \; -a -exec ls -l {} \; | sort | parallel ls -l

verwandte Informationen