Como faço para passar uma lista de arquivos para grep

89

Estou usando find e obtendo uma lista de arquivos para os quais quero grep . Como posso canalizar essa lista para grep ?

    
por Prospero 07.09.2011 / 20:27

2 respostas

100

Bem, o caso genérico que funciona com qualquer comando que grava no stdout é usar xargs , 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 linha grep 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 outros "caracteres estranhos" ( \'" para xargs, \[*? para $(find …) ).

No entanto, no caso específico de find , a capacidade de executar um programa nos argumentos fornecidos é incorporada:

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

Tudo entre -exec e ; é o comando para executar; {} é substituído pelo nome de arquivo encontrado por find . Isso executará um grep separado para cada arquivo; como grep pode pegar muitos nomes de arquivos e pesquisar todos eles, você pode alterar o ; para + para dizer ao find para passar todos os nomes de arquivos correspondentes para grep de uma só vez:

$ find … -exec grep 'search' {} \+
    
por 07.09.2011 / 20:43
7

Algumas versões de grep (por exemplo, em Linux não incorporado ou BSD ou Mac OS X) tem uma opção -r para fazer uma pesquisa recursiva. No OpenBSD, use -R (e não há --exclude como no exemplo abaixo). Isso abrange combinações simples de find com grep .

Se a sua implementação não tiver o sinal -R , ou se você quiser critérios mais sofisticados de correspondência de arquivos, poderá usar o -exec primário de find para torná-lo executar grep . Algumas implementações find mais antigas não suportam -exec+ ; nesses sistemas, use um ; em vez do + (isso chamará grep uma vez por arquivo, então será mais lento, mas caso contrário, o resultado será o mesmo). Observe o truque /dev/null para fazer com que grep mostre o nome do arquivo mesmo que ele seja chamado em um único arquivo (o GNU grep e o FreeBSD / NetBSD / OSX grep têm uma opção -H para obter o mesmo efeito).

find . -type f -name '*.o' -prune -o -exec grep 'needle' /dev/null {} +
grep -r --exclude='*.o' 'needle' .
    
por 08.09.2011 / 02:13

Tags