break out of find, wenn ein -exec fehlschlägt

14

Gibt es eine Möglichkeit, ein findso zu schreiben , dass es abbricht, wenn eine der -execOperationen für eine Datei fehlschlägt?

ZB ( javacwird praktischerweise als Programm verwendet, das für einige Dateien und aus keinem anderen Grund einen Exit-Code von 1 zurückgeben kann):

$ echo "public classXX A{}" >> A.java
$ echo "public class B{}" >> B.java
$ find . -iname \*.java -exec javac {} \;
./A.java:1: error: class, interface, or enum expected
public classXX A{}
       ^
1 error

In dem obigen Beispiel, obwohl die execauf der Datei A.javafehlgeschlagen (und zurück einen Exit - Code von 1), der findBefehl fort und Datei kompilierte B.javasowie. Gibt es eine Möglichkeit auszubrechen findoder sollte ich forstattdessen irgendeine Form von verwenden?

Meine Version von find:

$ find -version  | head -1
find (GNU findutils) 4.4.2
Marcus Junius Brutus
quelle

Antworten:

5

Meiner Ansicht nach...

find ... -exec sh -c 'cmd "$0" || kill $PPID' \{\} \;

... sollte für fast jeden den Trick machen find.

mikeserv
quelle
Vielen Dank an Gilles. Was macht der $0?
mikeserv
1
$0ist das erste Argument für sh -c( $1ist das zweite usw.) - üblicherweise der Name des ausgeführten Programms, aber hier führen Sie ein Snippet aus und übergeben den Dateinamen, der verarbeitet wird, als $0sinnvoll (z. B. als leicht erkennbar) es in ps). Es gibt eine Denkschule (der ich offensichtlich nicht angehöre), die besagt, dass $0sie immer ausführbar sein sollte und Sie sollten schreiben sh -c 'cmd "$1" …' sh {}oder so.
Gilles 'SO- hör auf böse zu sein'
@ Gilles - ziemlich glatt. Danke vielmals. Ich habe es im Auto auf dem Weg zur Vorschule herausgefunden, aber ich musste einige Minuten darüber nachdenken. Das ist schlau - ich werde es benutzen. Was mich wirklich angesprochen hat, war ein Schnitt, an den ich mich erinnerte, als ich Stephanes Artikel in einem Ihrer eigenen Beiträge gelesen hatte, in dem er find-sh $0am Ende einer findErklärung ein angefügt hatte . Dies scheint meiner Meinung nach nützlicher zu sein, obwohl es auf lange Sicht am wichtigsten ist, wonach Sie suchen.
mikeserv
Für den obigen Fall funktioniert es nicht. Nachdem die find . -iname \*.java -exec sh -c 'javac "${0}" || kill '$$ {} \;Datei A.javafehlgeschlagen ist und die Datei B.java trotzdem kompiliert wird.
Marcus Junius Brutus
@MarcusJuniusBrutus - Ich habe es behoben. Ich hätte deinen Kommentar früher sehen sollen. Nochmals Entschuldigung.
mikeserv
4

Zumindest mit GNU können findSie verwenden:

find ... -exec ... -o -quit
Hauke ​​Laging
quelle
Es scheint mir schwer zu fallen, klar zu machen, wo der Exec aufhört und das -o beginnt. Beide find . -iname \*.java -exec javac {} -o -quit \;und find . -iname \*.java -exec javac {} \; -o -quit \;scheitern (auf unterschiedliche Weise)
Marcus Junius Brutus
@MarcusJuniusBrutus \;wird am und vom -exec(dh vorher -o -quitin diesem Fall) benötigt, kann aber nirgendwo anders sein.
Hauke ​​Laging
2
Verwenden -exec ... -o -quitfunktioniert bei mir nicht. Es werden keine Dateien verarbeitet. Doch diese Linie funktioniert: find . -iname \*.java -not -exec javac '{}' \; -quit: -quitwird aufgerufen , wenn -execfalsch ist , dh. Gibt mit einem Wert ungleich Null zurück.
Savanto
find . -iname \*.java -exec javac {} \; -o -quitAuch kann keine Dateien verarbeiten. Merkwürdigerweise find . -iname \* -exec echo 'foo' \; -o -quit hat „Prozess“ , die Dateien.
Marcus Junius Brutus
0

Konsultieren Sie Ihr findHandbuch. @ Haukes Antwort hat mich motiviert zu schauen und QNXs Entdeckung hat eine -abortOption, die der GNU- -quitOption ähnlich zu sein scheint . Es funktioniert für mich, vorausgesetzt, ich verwende \(und \)gruppiere Ausdrücke:

find . -mtime -4 -name <pattern> \( -exec my_cmd {} \; -o  -abort \) 

Hinweis: Ohne die Parens wird die erste Datei abgebrochen.

Salbei
quelle