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

Réponses:


5

Je pense...

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

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


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

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.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.