salir de la búsqueda si falla un -exec

14

¿Hay alguna manera de escribir un mensaje findpara que se rompa si una de las -execoperaciones falla en un archivo?

Por ejemplo ( javacse usa convenientemente como un programa que puede devolver un código de salida de 1 en algunos archivos y sin ningún otro motivo):

$ 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

En el ejemplo anterior, aunque el execarchivo A.javafalló (y devolvió un código de salida de 1), el findcomando continuó y también compiló el archivo B.java. ¿Hay alguna manera de salir findo debería usar alguna forma de en su forlugar?

Mi versión de find:

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

Respuestas:

5

Yo creo que...

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

... debería hacer el truco para casi cualquiera find.

mikeserv
fuente
Gracias @Gilles. ¿Qué hace el $0?
mikeserv
1
$0es el primer argumento para sh -c( $1es el segundo, etc.): convencionalmente el nombre del programa que se está ejecutando, pero aquí está ejecutando un fragmento, y pasar el nombre del archivo que se está procesando $0tiene sentido (por ejemplo, puede ver fácilmente en ps). Hay una escuela de pensamiento (a la que obviamente no pertenezco) que establece que $0siempre debe ser ejecutable y que debe escribir sh -c 'cmd "$1" …' sh {}o algo así.
Gilles 'SO- deja de ser malvado'
@Gilles: bastante hábil. Muchas gracias. Lo descubrí en el auto camino al preescolar, pero tuve que pensarlo por varios minutos. Eso es inteligente, lo voy a usar. Lo que realmente hizo clic para mí fue una edición que recordé haber leído de Stephane en una de sus propias publicaciones en la que agregó un find-sh $0al final de una finddeclaración. Esto parece más útil en mi opinión, aunque creo que es lo que buscas a largo plazo lo que más importa.
mikeserv
No está funcionando para el caso anterior. Después de que el find . -iname \*.java -exec sh -c 'javac "${0}" || kill '$$ {} \;archivo A.javafalla y, aún así, el archivo B.java se compila.
Marcus Junius Brutus
@MarcusJuniusBrutus: lo arreglé. Debería haber visto tu comentario antes. Lo siento, nuevamente.
mikeserv
4

Al menos con GNU findpuedes usar:

find ... -exec ... -o -quit
Hauke ​​Laging
fuente
Parece que tengo problemas para dejar en claro dónde se detiene el ejecutivo y dónde comienza el -o. Ambos find . -iname \*.java -exec javac {} -o -quit \;y find . -iname \*.java -exec javac {} \; -o -quit \;fallan (de diferentes maneras)
Marcus Junius Brutus
@MarcusJuniusBrutus \;es necesario en el y de -exec(es decir, antes -o -quiten este caso) pero puede que no esté en ningún otro lado.
Hauke ​​Laging
2
Usar -exec ... -o -quitno me funciona. No procesa ningún archivo. Sin embargo, esta línea funciona: find . -iname \*.java -not -exec javac '{}' \; -quit: -quitse llama si -execes falsa, es decir. devuelve con un valor distinto de cero.
Savanto 05 de
find . -iname \*.java -exec javac {} \; -o -quittampoco puede procesar ningún archivo. Curiosamente, find . -iname \* -exec echo 'foo' \; -o -quit hace del "proceso" los archivos.
Marcus Junius Brutus
0

Consulte su findmanual. La respuesta de @ Hauke ​​me motivó a mirar y el hallazgo de QNX tiene una -abortopción que parece similar a la -quitopción GNU . Funciona para mí siempre que use \(y \)para agrupar expresiones:

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

Nota: sin los parens, aborta en el primer archivo.

sabio
fuente