saia da descoberta se um -exec falhar


14

Existe uma maneira de escrever um findpara que ele se quebre se uma das -execoperações falhar em um arquivo?

Por exemplo ( javacé convenientemente usado como um programa que pode retornar um código de saída 1 em alguns arquivos e por nenhum outro 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

No exemplo acima, apesar execde o arquivo A.javafalhar (e retornar um código de saída 1), o findcomando prosseguiu e o arquivo compilado B.javatambém. Existe uma maneira de sair findou devo usar alguma forma de alternativa for?

Minha versão do find:

$ find -version  | head -1
find (GNU findutils) 4.4.2

Respostas:


5

Eu acho que...

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

... deve fazer o truque para praticamente qualquer find.


Obrigado @Gilles. O que $0faz?
mikeserv

1
$0é o primeiro argumento para sh -c( $1é o segundo, etc.) - convencionalmente o nome do programa que está sendo executado, mas aqui você está executando um trecho e passando o nome do arquivo que está sendo processado como $0faz algum sentido (por exemplo, você vê facilmente em ps). Existe uma escola de pensamento (da qual obviamente não pertenço) que afirma que $0sempre deve ser executável e que você deve escrever sh -c 'cmd "$1" …' sh {}ou algo assim.
Gilles 'SO- stop be evil'

@ Gilles - muito liso. Muito obrigado. Eu descobri no carro a caminho da pré-escola, mas tive que pensar nisso por alguns minutos. Isso é inteligente - eu vou usá-lo. O que realmente me chamou atenção foi uma edição que eu lembrei de ler de Stephane em uma de suas próprias postagens, na qual ele adicionou uma find-sh $0no final de uma finddeclaração. Isso parece mais útil na minha opinião, embora eu acho que é o que você mais procura no longo prazo.
mikeserv

Não está funcionando para o caso acima. Depois que o find . -iname \*.java -exec sh -c 'javac "${0}" || kill '$$ {} \;arquivo A.javafalha e, ainda assim, o arquivo B.java é compilado.
Marcus Junius Brutus 06/06

@MarcusJuniusBrutus - eu consertei. Eu deveria ter visto seu comentário anteriormente. Mais uma vez, desculpe.
mikeserv

4

Pelo menos com o GNU findvocê pode usar:

find ... -exec ... -o -quit

Parece que tenho problemas para esclarecer onde o executivo para e o -o começa. Ambos find . -iname \*.java -exec javac {} -o -quit \;e find . -iname \*.java -exec javac {} \; -o -quit \;falhar (de diferentes maneiras)
Marcus Junius Brutus

@MarcusJuniusBrutus \;é necessário no e de -exec(ou seja, antes -o -quitneste caso), mas pode estar em nenhum outro lugar.
Hauke ​​Laging

2
Usar -exec ... -o -quitnão funciona para mim. Não processa nenhum arquivo. No entanto, esta linha funciona: find . -iname \*.java -not -exec javac '{}' \; -quit: -quité chamado, se -execé falso, ie. retorna com diferente de zero.
savanto

find . -iname \*.java -exec javac {} \; -o -quittambém falha ao processar qualquer arquivo. Estranhamente, find . -iname \* -exec echo 'foo' \; -o -quit faz "processo" os arquivos.
Marcus Junius Brutus

0

Consulte o seu findmanual. A resposta de @ Hauke ​​me motivou a procurar e a descoberta do QNX tem uma -abortopção que parece semelhante à -quitopção GNU . Funciona para mim desde que eu use \(e \)agrupe expressões:

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

Nota: sem as parênteses, é interrompido no primeiro arquivo.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.