Estou usando find
e obtendo uma lista de arquivos pelos quais desejo grep
passar. Como canalizo essa lista para grep
?
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 grep
linha 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 find
capacidade de executar um programa nos argumentos fornecidos, está embutido:
$ find … -exec grep 'search' {} \;
Tudo entre -exec
e ;
é o comando a ser executado; {}
é substituído pelo nome do arquivo encontrado por find
. Isso executará um separado grep
para cada arquivo; como grep
pode 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 grep
uma só vez:
$ find … -exec grep 'search' {} \+
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.-exec
, em vez de oxargs
. Se você usar o-exec
infind
, ele criará apenas um shell para grep para o conteúdo. Se você usar oxargs
, ele criará dois shells: um para ofind
e outro para oxargs
.$ find … -exec grep 'search' {} \+
formulário é muito mais rápido.Algumas versões
grep
(por exemplo, no Linux, BSD ou Mac OS X não incorporado ) têm uma-r
opção para fazer uma pesquisa recursiva. No OpenBSD, use-R
(e não há--exclude
como no exemplo abaixo). Isso abrange combinações simples defind
comgrep
.Se sua implementação não possui o
-R
sinalizador ou se você deseja critérios de correspondência de arquivo mais sofisticados, use o-exec
principal defind
para executá-logrep
. Algumasfind
implementações mais antigas não suportam-exec
…+
; nesses sistemas, use um em;
vez de+
(isso será chamadogrep
uma vez por arquivo, portanto será mais lento, mas, caso contrário, o resultado será o mesmo). Observe o/dev/null
truque paragrep
mostrar o nome do arquivo, mesmo que seja chamado em um único arquivo (o GNU grep e o FreeBSD / NetBSD / OSX grep têm uma-H
opção para obter o mesmo efeito).fonte
GNU grep
tem-H
opção para sempre imprimir o nome do arquivo.