Como passo uma lista de arquivos para grep

98

Estou usando finde obtendo uma lista de arquivos pelos quais desejo greppassar. Como canalizo essa lista para grep?

Arcabard
fonte

Respostas:

116

Bem, o caso genérico que funciona com qualquer comando que grava no stdout é usar xargs, o que permitirá anexar qualquer número de argumentos da linha de comando ao final de um comando:

$ find … | xargs grep 'search'

Ou para incorporar o comando na sua greplinha com backticks ou $(), que executará o comando e substituirá sua saída:

$ grep 'search' $(find …)

Observe que esses comandos não funcionam se os nomes dos arquivos contiverem espaços em branco ou certos outros "caracteres estranhos" ( \'"para xargs, \[*?para $(find …)).


No entanto, no caso específico da findcapacidade de executar um programa nos argumentos fornecidos, está embutido:

$ find … -exec grep 'search' {} \;

Tudo entre -exece ;é o comando a ser executado; {}é substituído pelo nome do arquivo encontrado por find. Isso executará um separado greppara cada arquivo; como greppode pegar muitos nomes de arquivos e pesquisar em todos, você pode alterar ;para +to tell find para passar todos os nomes de arquivos correspondentes de grepuma só vez:

$ find … -exec grep 'search' {} \+
Michael Mrozek
fonte
1
Deve-se notar que os dois primeiros formulários não funcionam com nomes de arquivos que contêm espaços.
enzotib 7/09/11
1
Eu prefiro find ... -type f -print0 | xargs -r0 grep 'search' /dev/null. QED. Embora -exec +seja muito eficiente, ele não existe em todas as versões do find.
Arcege
Infelizmente eu não posso verificar se você corrige 3 vezes.
Arcabard 7/09/11
3
Sugiro usar o -exec, em vez de o xargs. Se você usar o -execin find, ele criará apenas um shell para grep para o conteúdo. Se você usar o xargs, ele criará dois shells: um para o finde outro para o xargs.
2
pela experiência, acho que o $ find … -exec grep 'search' {} \+formulário é muito mais rápido.
gogoud
9

Algumas versões grep(por exemplo, no Linux, BSD ou Mac OS X não incorporado ) têm uma -ropção para fazer uma pesquisa recursiva. No OpenBSD, use -R(e não há --excludecomo no exemplo abaixo). Isso abrange combinações simples de findcom grep.

Se sua implementação não possui o -Rsinalizador ou se você deseja critérios de correspondência de arquivo mais sofisticados, use o -execprincipal de findpara executá-lo grep. Algumas findimplementações mais antigas não suportam -exec+; nesses sistemas, use um em ;vez de +(isso será chamado grepuma vez por arquivo, portanto será mais lento, mas, caso contrário, o resultado será o mesmo). Observe o /dev/nulltruque para grepmostrar o nome do arquivo, mesmo que seja chamado em um único arquivo (o GNU grep e o FreeBSD / NetBSD / OSX grep têm uma -Hopção para obter o mesmo efeito).

find . -type f -name '*.o' -prune -o -exec grep 'needle' /dev/null {} +
grep -r --exclude='*.o' 'needle' .
Gilles
fonte
2
GNU greptem -Hopção para sempre imprimir o nome do arquivo.
enzotib 8/09/11