
Estou tentando executar vários comandos em coisas que encontrei. Como posso conseguir isso?
find . -exec cmd1; cmd2
parece não funcionar; em vez disso, ele executa o cmd2 após o cmd1 ter sido executado em todos os arquivos.
Responder1
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 deste tipo seria assim:
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 para "falso" e -o
faz com que a próxima expressão (a segunda -exec
) seja avaliada por causa do -false
.
De man find
:
expr1 expr2
Duas expressões seguidas são consideradas unidas por um "e" implícito; expr2 não é avaliado se expr1 for falso.expr1 -a expr2
O mesmo que expr1 expr2.expr1 -o expr2
Ou; expr2 não é avaliado se expr1 for verdadeiro.
Responder2
Se você não se importa com o fato de o cmd1 ser capaz de impedir a execução do cmd2 devido ao código de erro 0
:
find . -exec cmd1 \; -exec cmd2 \;
A única maneira confiável de fazer com que ambos os comandos sempre executem isso é invocar find
um shell que posteriormente executará os comandos em sequência:
find . -exec bash -c 'cmd1; cmd2' filedumper {} \;
Responder3
Se você não se importa em criar um script que execute cmd1 e cmd2, é apenas isto:
find . -exec myscript {} \;
ou
find . -exec myscript {} +
Usar \; ou + dependendo se o myscript pode lidar com mais de um arquivo por vez (fica complicado 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ê tiver que fazer isso uma vez, terá que fazer novamente.
Mas um truque legal é colocar o achadodentroo roteiro:
if [ $# -gt 0 ]; then
for each; do
touch $each
done
else
find . -exec $0 {} +
fi
Então myscript funciona em quaisquer arquivos que você fornecer como argumentos para funcionar, mas se você não fornecer nenhum argumento, ele executará find no diretório atual e, em seguida, chamará a si mesmo nos arquivos encontrados. Isso contorna o fato de que find -exec não pode chamar funções shell que você definiu em seu script.
Responder4
tente o comando:
sudo find -name "*[!0-9][1-9].txt" -exec chmod 744 * {} \; -a -exec ls -l {} \; | sort | parallel ls -l