Estou tentando executar vários comandos nas coisas que encontrei, como posso conseguir isso?
find . -exec cmd1; cmd2
parece não funcionar; em vez disso, executa o cmd2 após a execução do cmd1 em todos os arquivos.
Estou tentando executar vários comandos nas coisas que encontrei, como posso conseguir isso?
find . -exec cmd1; cmd2
parece não funcionar; em vez disso, executa o cmd2 após a execução do cmd1 em todos os arquivos.
Respostas:
Nesta demonstração, usarei sh -c 'echo first; false'
(ou true
) para o primeiro -exec
. Isso fornecerá alguma saída e também terá o efeito do código de saída selecionado. Então echo second
será usado para o segundo. Suponha que haja um arquivo no diretório atual.
$ find . -type f -exec sh -c 'echo first; false' \; -exec echo second \;
first
$ find . -type f -exec sh -c 'echo first; true' \; -exec echo second \;
first
second
$ find . -type f \( -exec sh -c 'echo first; false' \; -false -o -exec echo second \; \)
first
second
$ find . -type f \( -exec sh -c 'echo first; false' \; -false -o -exec echo second \; \)
first
second
Um comando real desse tipo seria semelhante a:
find . -type f \( -exec command1 \; -false -o -exec command2 \; \)
No segundo conjunto, os parênteses escapados agrupam as duas -exec
cláusulas. O -false
entre eles força o estado de teste a "falso" e -o
faz com que a próxima expressão (a segunda -exec
) seja avaliada devido a -false
.
De man find
:
expr1 expr2
Duas expressões em uma linha são usadas para serem unidas com um "e" implícito; expr2 não é avaliado se expr1 for falso.expr1 -a expr2 O
mesmo que expr1 expr2.expr1 -o expr2
Or; expr2 não é avaliado se expr1 for verdadeiro.
Se você não importa se o cmd1 pode impedir a execução do cmd2 devido ao código de erro 0
:
find . -exec cmd1 \; -exec cmd2 \;
A única maneira confiável de obter sempre que ambos os comandos executem isso é find
chamar um shell que posteriormente executará os comandos em sequência:
find . -exec bash -c 'cmd1; cmd2' filedumper {} \;
Se você não se importa de criar um script que faça cmd1 e cmd2, é apenas isso:
find . -exec myscript {} \;
ou
find . -exec myscript {} +
Usar \; ou + dependendo se o myscript pode lidar com mais de um arquivo por vez (fica peludo se houver espaços nos nomes dos arquivos, etc.).
Colocar o que você estava fazendo em um roteiro, na minha experiência, quase sempre valeu a pena. Se você precisar fazer isso uma vez, precisará fazê-lo novamente.
Mas um truque é colocar a descoberta dentro do script:
if [ $# -gt 0 ]; then
for each; do
touch $each
done
else
find . -exec $0 {} +
fi
Em seguida, o myscript funciona em qualquer arquivo que você fornecer como argumento, mas se você não fornecer nenhum argumento, ele executará find a partir do diretório atual e se chamará nos arquivos encontrados. Isso contorna o fato de que find -exec não pode chamar funções de shell que você definiu em seu script.
Eu tenho tentado ambas as soluções anteriores sem muita sorte. Este funcionou muito bem para mim:
$ for i in `find . -exec echo {} \;`; do cmd1 $i; cmd2 $i; done
comando try:
sudo find -name "*[!0-9][1-9].txt" -exec chmod 744 * {} \; -a -exec ls -l {} \; | sort | parallel ls -l
*
na -exec
parte será expandido para todos os arquivos no diretório atual. Especialmente quando executando como sudo
.
-o
.