- "Obviamente"
-exec …
deve ser terminado com um ponto-e-vírgula ( ;
) ou um sinal de mais ( +
). Ponto e vírgula é um caractere especial no shell (ou, pelo menos, a cada escudo que eu já utilizado), por isso, se é para ser usado como parte do find
comando , ele deve ser precedido ou cotados ( \;
, ";"
ou ';'
).
Com -exec … ;
, a {}
cadeia pode aparecer várias vezes no comando, incluindo zero ou duas ou mais, em qualquer posição.
Veja isso
para um exemplo de por que você pode querer fazer -exec
sem usar {}
.
Ter duas ou mais aparências é útil principalmente porque, em (pelo menos) algumas versões do find
, {}
não precisa ser uma palavra por si só; pode ter outros caracteres no começo ou no fim; por exemplo,
find . -type f -exec mv {} {}.bak ";"
Com -exec … +
, a {}
cadeia deve aparecer como o último argumento antes do +
. Um comando como
find . -name "*.bak" -exec mv {} backup_folder +
resulta na find: missing argument to ‘-exec’
mensagem de erro enigmática .
Uma solução alternativa específica para os comandos cp
e mv
é
find . -name "*.bak" -exec mv -t backup_folder {} +
ou
find . -name "*.bak" -exec mv --target-directory=backup_folder {} +
O {}
deve ser uma palavra por si só; não pode ter outros caracteres no começo ou no final. E, em (pelo menos) algumas versões find
, você pode não ter mais de uma {}
.
Uma nota de sanidade: você pode dizer
encontrar . -name "* .sh" -type f -executable -exec {} args opcionais aqui ";"
para executar cada um dos seus scripts. Mas
encontrar . -name "* .sh" -tipo f -executable -exec {} +
executa um de seus scripts, com os nomes de todos os outros como parâmetros. Isso é semelhante a dizer
./*.sh
como um comando shell, exceto find
que não garante que ele classifique seus resultados, portanto você não tem garantia de execução aaa.sh
(seu primeiro *.sh
arquivo em ordem alfabética ) como seria com a execução ./*.sh
.
Um aspecto find
que pode não estar perfeitamente claro para iniciantes é que a linha de comando é, efetivamente, uma declaração executável em um idioma misterioso. Por exemplo,
find . -name "*.sh" -type f -executable -print
significa
for each file
if the file’s name matches `*.sh` (i.e., if it ends with `.sh`)
then
if it is a plain file (i.e., not a directory)
then
if it is executable (i.e., the appropriate `---x--x--x` bit is set)
then
print the file’s name
end if
end if
end if
end loop
ou simplesmente,
for each file
if the file’s name matches `*.sh` AND it is a plain file AND it is executable
then
print the file’s name
end if
end loop
Algumas das -
palavras - chave são uma ação executável e um teste. Em particular, isso é verdade para -exec … ;
; por exemplo,
find . -type f -exec grep -q cat {} ";" -print
traduz para
para cada arquivo
se for um arquivo simples (ou seja, não um diretório)
então
execute o nome do arquivo grep -q cat
se o processo for bem-sucedido (ou seja, sai com o status 0)
então
imprime o nome do arquivo
fim se
fim se
laço final
que imprimirá os nomes de todos os arquivos que contêm a string “ cat
”. E, embora isso seja algo que grep
possa ser feito sozinho (com a opção -l
(minúscula L
)), pode ser útil usá-lo find
para encontrar arquivos que contenham uma determinada string E tenham um determinado tamanho E sejam de propriedade de um determinado proprietário E foram modificados em um determinado intervalo de tempo,….
No entanto, isso não funciona -exec … +
. Como -exec … +
executa um comando para vários arquivos, não faz sentido usá-lo como uma condição lógica dentro de um for each file …
loop.
- O outro lado da situação acima é que
find
geralmente sai com um status de saída 0, a menos que você dê argumentos inválidos ou encontre um diretório que não pode ler. Mesmo se um programa que você executa falhar (sai com um status de saída diferente de zero),
find
sai com um status de saída igual a 0.
Exceto se um programa que você executa com -exec … +
falha (sai com um status de saída diferente de zero)
find
sai com um status de saída diferente de zero.
... -exec mv {} {}.bak ...
não é garantido para funcionar como esperado em todas asfind
implementações. Os estados padrão POSIX{}
devem parecer sozinhos para serem sempre reconhecidos; caso contrário, o comportamento é livre para manter os caracteres inalterados ou substituí-los pelo nome do caminho. No primeiro caso, o seu comando inteiro vai essencialmente apagar todos os arquivos, mas o último encontrado ...