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.
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.
Antworten:
In dieser Demonstration werde ich sh -c 'echo first; false'
(oder true
) für die erste verwenden -exec
. Das gibt etwas aus und hat auch den ausgewählten Exit-Code-Effekt. Dann echo second
wird für die zweite verwendet. Angenommen, im aktuellen Verzeichnis befindet sich eine Datei.
$ 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 so aussehen:
find . -type f \( -exec command1 \; -false -o -exec command2 \; \)
Im zweiten Satz gruppieren die -exec
geschützten Klammern die beiden Klauseln. Das -false
dazwischenliegende erzwingt den Testzustand auf "false" und -o
bewirkt, dass der nächste Ausdruck (der zweite -exec
) aufgrund von "false" ausgewertet wird -false
.
Von man find
:
expr1 expr2
Zwei Ausdrücke in einer Reihe werden verwendet, um mit einem impliziten "und" verbunden zu werden. Ausdruck2 wird nicht ausgewertet, wenn Ausdruck1 falsch ist.Ausdruck1 -a Ausdruck2
Entspricht Ausdruck1 Ausdruck2.expr1 -o expr2
Oder; Ausdruck2 wird nicht ausgewertet, wenn Ausdruck1 wahr ist.
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, beide Befehle immer ausführen zu lassen, besteht darin find
, eine Shell aufzurufen, die die Befehle anschließend nacheinander ausführt:
find . -exec bash -c 'cmd1; cmd2' filedumper {} \;
Wenn es Ihnen nichts ausmacht, ein Skript zu erstellen, das cmd1 und cmd2 ausführt, dann ist es nur Folgendes:
find . -exec myscript {} \;
oder
find . -exec myscript {} +
Verwenden \; oder + abhängig davon, ob myscript mehr als eine Datei gleichzeitig verarbeiten kann (wird haarig, wenn in Dateinamen Leerzeichen usw. enthalten sind).
Nach meiner Erfahrung hat es sich fast immer gelohnt, in ein Drehbuch zu schreiben, was Sie getan haben. Wenn Sie es einmal tun müssen, müssen Sie es erneut tun.
Ein guter Trick ist jedoch, den Fund in das Skript einzufügen:
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, damit es funktioniert. Wenn Sie jedoch keine Argumente angeben, wird find aus dem aktuellen Verzeichnis ausgeführt und die gefundenen Dateien aufgerufen. Dies umgeht die Tatsache, dass find -exec keine Shell-Funktionen aufrufen kann, die Sie in Ihrem Skript definiert haben.
Ich habe beide vorherigen Lösungen ohne viel Glück ausprobiert. Dieser hat für mich gut funktioniert:
$ for i in `find . -exec echo {} \;`; do cmd1 $i; cmd2 $i; done
try Befehl:
sudo find -name "*[!0-9][1-9].txt" -exec chmod 744 * {} \; -a -exec ls -l {} \; | sort | parallel ls -l
*
im -exec
Teil wird auf alle Dateien im aktuellen Verzeichnis erweitert. Besonders beim Laufen als sudo
.
-o
.