Existe uma maneira mais simples de grep todos os arquivos em um diretório?

20

Quando eu quero pesquisar uma árvore inteira por algum conteúdo, eu uso

find . -type f -print0 | xargs -0 grep <search_string>

Existe uma maneira melhor de fazer isso em termos de desempenho ou brevidade?

    
por Dancrumb 16.08.2017 / 18:28

5 respostas

41

Verifique se a sua opção grep suporta -r (para recurse ):

grep -r <search_string> .
    
por 16.08.2017 / 18:30
12

Se você quiser recorrer aos subdiretórios:

grep -R 'pattern' .

A opção -R não é uma opção padrão, mas é suportada pelas implementações mais comuns de grep .

    
por 16.08.2017 / 18:32
12

Uma resposta ótima: Em vez de canalizar a saída de find para grep , você poderia simplesmente executar

find . -type f -exec grep 'research' {} '+'

e voila, um comando em vez de dois!

explicação:

find . -type f

encontre todos os arquivos regulares em.

-exec grep 'research'

grep 'research'

{}

no nome do arquivo encontrado

'+'

use um comando para todos os nomes de arquivos, não uma vez por nome de arquivo.

Nb: com ';' teria sido uma vez por nome de arquivo.

Além disso, se você usar isso para processar o código-fonte, poderá procurar em ack , que é feito para procurar bits de código facilmente.

ack

Editar:

Você pode estender essa pesquisa um pouco. Primeiro, você pode usar a opção -name '' de find para procurar arquivos com o padrão de nomenclatura specifig.

Por exemplo:

  • apenas arquivos que correspondem a registros: -name '*.log'

  • apenas arquivos que correspondem aos cabeçalhos c, mas você não pode ficar com maiúsculas ou minúsculas nas extensões de nome de arquivo: -iname *.c

Nb: como para grep e ack , a opção -i não diferencia maiúsculas de minúsculas neste caso.

Nesse caso, o grep será exibido sem cor e sem números de linha.

Você pode alterar isso com as opções --color e -n (números de cor e linhas nos arquivos, respectivamente).

No final, você pode ter algo como:

find . -name '*.log' -type f -exec grep --color -n 'pattern' {} '+'

por exemplo

$ find . -name '*.c' -type f -exec grep -n 'hello' {} '+' 
./test2/target.c:1:hello
    
por 16.08.2017 / 19:58
5

Como mencionado acima, -r ou -R (dependendo do tratamento desejado do symlink) é uma opção rápida.

No entanto, -d <action> pode ser útil às vezes.

O interessante sobre -d é o comando skip, que silencia o "grep: directory_name: É um diretório "quando você quer apenas varrer o nível atual.

$ grep foo * 
grep: q2: Is a directory 
grep: rt: Is a directory 

$ grep -d skip foo *  
$ 

e claro:

$ grep -d recurse foo * 
(list of results that don't exist because the word foo isn't in our source code
and I wouldn't publish it anyway).  
$ 

A opção -d skip é realmente útil em outro script, portanto, você não precisa 2> /dev/null . :)

    
por 16.08.2017 / 21:10
0

Se você está lidando com muitos arquivos, o grep roda mais rápido se você remover os arquivos que precisa pesquisar em vez de copiar todos os arquivos em subpastas.

Eu uso este formato às vezes:

grep "primary" 'find . | grep cpp$'

Encontre todos os arquivos nas subpastas de . que terminam em cpp . Então grep esses arquivos para "primário".

Se você quiser, pode manter os resultados em outras chamadas do grep:

grep "primary" 'find . | grep cpp$' | grep -v "ignoreThis" | grep -i "caseInsensitiveGrep"
    
por 17.08.2017 / 21:28

Tags