Existe uma maneira de combinar logicamente dois comandos de shell que são chamados com o find - exec ?
Por exemplo, para imprimir todos os arquivos .csv que contêm a string foo juntamente com a ocorrência, eu gostaria de fazer:
find . -iname \*.csv -exec grep foo {} && echo {} \;
mas o bash reclama com "falta de argumento para '-exec'"
-exec
em sequência ou usar um único-exec sh -c 'grep foo "$0" && printf %s\\n "$0"' {} \;
.sh
(neste caso{}
) seja$1
e$0
será algo comosh
. Mas, na verdade, você está correto, o primeiro argumento aparece como$0
. Ter o primeiro argumento como o nome do comando de chamada é apenas uma convenção, que não é aplicada automaticamente nesses casos.Respostas:
-exec
é um predicado que executa um comando (não um shell) e é avaliado como verdadeiro ou falso com base no resultado do comando (status de saída zero ou diferente de zero).Tão:
iria imprimir o caminho do arquivo se
grep
encontra foo no arquivo. Em vez de-print
você pode usar outro-exec
predicado ou qualquer outro predicadoVeja também os operadores
!
e-o
encontre para negação e ou .Como alternativa, você pode iniciar um shell como:
Ou, para evitar a necessidade de iniciar um shell para cada arquivo:
fonte
O problema que você está enfrentando é que o shell analisa primeiro a linha de comando e vê dois comandos simples separados pelo
&&
operador:,find . -iname \*.csv -exec grep foo {}
eecho {} \;
. Citando&&
(find . -iname \*.csv -exec grep foo {} '&&' echo {} \;
) ignora isso, mas agora o comando executado porfind
algo comogrep
com os argumentosfoo
,wibble.csv
,&&
,echo
ewibble.csv
. Você precisa instruirfind
para executar um shell que interpretará o&&
operador:Observe que o primeiro argumento a seguir
sh -c SOMECOMMAND
é$0
não$1
.Você pode economizar o tempo de inicialização de um processo de shell para cada arquivo agrupando as chamadas de comando
-exec … +
. Para facilitar o processamento, passe algum valor fictício$0
para"$@"
enumerar os nomes dos arquivos.Se o comando shell tiver apenas dois programas separados por
&&
, elefind
poderá-exec
executar o trabalho sozinho: escreva duas ações consecutivas e a segunda será executada apenas se a primeira sair com o status 0.(Presumo que
grep
eecho
são apenas para fins de ilustração, como-exec echo
pode ser substituído por-print
e a saída resultante não é particularmente qualquer maneira útil.)fonte
./some-file: grep: command not found
mensagem de erro confusa .-exec find sh -c '... "$1"' sh {} \;
não teria o problema. Há um erro de digitação (relacionado) no seu segundo comando find.Nesse caso específico, eu faria:
find . -iname \*.csv -exec grep -l foo \{\} \;
Ou se você concorda :
ack -al -G '.*\.csv' foo
Para responder à sua pergunta real, algo como isto pode funcionar:
find . -iname \*.csv -exec sh -c "grep foo {} && echo {}" \;
fonte