O fator chave para alcançar find
enlightenment;) é:
find
's business is evaluating expressions -- not locating files. Yes,find
certainly locates files; but that's really just a side effect.
Existe uma abordagem alternativa a essa questão que vale a pena conhecer (como também descrito em Unix Power Tools, na seção " Usando -exec para criar testes personalizados "):
find . -type f -exec sh -c 'file -b "$1" | grep -iqE "^ELF|^C source"' sh {} \; -print
Vale a pena conhecer esse método de filtragem, já que ele pode ser usado para muitas outras coisas além de simplesmente imprimir o nome do arquivo; apenas mude o operador -print
para qualquer outro operador que você gostar (incluindo outro operador -exec
) e faça o que quiser com ele.
Existe uma desvantagem de desempenho para este comando (que também está presente em a outra resposta ), que é que, como estamos usando \;
e não +
, estamos gerando um shell para cada arquivo. Usar +
para passar vários arquivos de uma vez para o comando sh
e processá-los com um loop for
fornece uma vantagem perceptível de desempenho:
find . -exec sh -c 'for f do file -b "$f" | grep -qE "^ELF|^C source" && printf %s\n "$f"; done' sh {} +
Você pode ver a comparação para si mesmo executando os dois comandos a seguir e comparando a saída de time
:
time find . -exec sh -c 'for f do file -b "$f" | grep -qE "^ELF|^C source" && printf %s\n "$f"; done' sh {} +
time find . -exec sh -c 'file -b "$1" | grep -qE "^ELF|^C source" && printf %s\n "$1"' sh {} \;
O ponto real, no entanto, é:
Nunca execute um loop for
do shell em uma lista de arquivos com saída de find
. Em vez disso, execute a ação que você precisa fazer em cada arquivo diretamente em find
de usando o operador -exec
, ou embed um shell for
loop dentro de um comando find
e faça desta forma.
Algumas razões adicionais: