sortir de la recherche si un -exec échoue

14

Existe-t-il un moyen d'écrire un findafin qu'il se casse si l'une des -execopérations échoue sur un fichier?

Par exemple ( javacest commodément utilisé comme un programme qui peut retourner un code de sortie de 1 sur certains fichiers et pour aucune autre raison):

$ 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

Dans l'exemple ci-dessus, bien que le execfichier ait A.javaéchoué (et renvoyé un code de sortie de 1), la findcommande a également exécuté et compilé le fichier B.java. Existe-t-il un moyen de sortir findou dois-je utiliser une forme quelconque à la forplace?

Ma version de find:

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

Réponses:

5

Je pense...

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

... devrait faire l'affaire pour à peu près tout find.

mikeserv
la source
Merci @Gilles. Que fait- $0il?
mikeserv
1
$0est le premier argument de sh -c( $1est le deuxième, etc.) - conventionnellement le nom du programme en cours d'exécution, mais ici vous exécutez un extrait de code, et le passage du nom de fichier en cours de traitement $0est logique (par exemple, vous voyez facilement en ps). Il y a une école de pensée (à laquelle je n'appartiens évidemment pas) qui déclare qu'il $0devrait toujours être exécutable et que vous devriez écrire sh -c 'cmd "$1" …' sh {}ou quelque chose du genre.
Gilles 'SO- arrête d'être méchant'
@Gilles - assez lisse. Merci beaucoup. Je l'ai compris dans la voiture sur le chemin de l'école maternelle, mais j'ai dû y réfléchir pendant plusieurs minutes. C'est intelligent - je vais l'utiliser. Ce qui m'a vraiment cliqué dessus, c'est une modification dont je me souviens avoir lu Stéphane sur l'un de vos propres postes dans lequel il a ajouté un find-sh $0à la fin d'une finddéclaration. Cela semble plus utile à mon avis, même si je suppose que c'est ce que vous recherchez à long terme qui compte le plus.
mikeserv
Cela ne fonctionne pas pour le cas ci-dessus. Après l' échec du find . -iname \*.java -exec sh -c 'javac "${0}" || kill '$$ {} \;fichier A.javaet toujours le fichier B.java est compilé.
Marcus Junius Brutus
@MarcusJuniusBrutus - Je l'ai corrigé. J'aurais dû voir votre commentaire plus tôt. Encore désolé.
mikeserv
4

Au moins avec GNU, findvous pouvez utiliser:

find ... -exec ... -o -quit
Hauke ​​Laging
la source
Il me semble que j'ai du mal à préciser où s'arrête l'exécuteur et où commence -o. Les deux find . -iname \*.java -exec javac {} -o -quit \;et find . -iname \*.java -exec javac {} \; -o -quit \;échouent (de différentes manières)
Marcus Junius Brutus
@MarcusJuniusBrutus \;est nécessaire au et de -exec(c'est-à-dire avant -o -quitdans ce cas) mais peut être nulle part ailleurs.
Hauke ​​Laging
2
L'utilisation -exec ... -o -quitne fonctionne pas pour moi. Il ne traite aucun fichier. Cependant cette ligne fonctionne: find . -iname \*.java -not -exec javac '{}' \; -quit: -quitest appelée si -execest fausse, à savoir. renvoie avec non nul.
savanto
find . -iname \*.java -exec javac {} \; -o -quitéchoue également à traiter les fichiers. Étrangement, le find . -iname \* -exec echo 'foo' \; -o -quit fait de « processus » les fichiers.
Marcus Junius Brutus
0

Consultez votre findmanuel. @ La réponse de Hauke ​​m'a motivé à regarder et la recherche de QNX a une -abortoption qui semble similaire à l' -quitoption GNU . Cela fonctionne pour moi à condition d'utiliser \(et \)de regrouper les expressions:

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

Remarque: sans les parens, il s'interrompt sur le premier fichier.

sauge
la source