grep recursivo: excluir diretórios específicos

49

Eu uso muito o grep recursivo para encontrar arquivos de origem com conteúdo específico.

grep -Rni "myfunc" .

Em grandes bases de código, isso pode ficar lento, então eu uso --incldue para restringir / adicionar extensões à lista de permissões.

grep -Rni --include=*.java "myfunc" .

No entanto, seria mais eficiente excluir (remover) subdiretórios inteiros, estou pensando:

grep -Rni --exclude=/.svn/ "myfunc" .

Mas o --exclude suporta apenas padrões de arquivo como * .java acima. Como posso excluir diretórios?

gabor
fonte

Respostas:

10

Você pode procurar em ack .

Eu apenas comecei a usá-lo, mas parece adequado para isso.

Alex Feinman
fonte
ack parece muito bom. É bom excluir intuitivamente arquivos indesejados. a opção --nogroup dá uma saída semelhante ao grep -Rni
Gabor
2
Ack é um pouco lento. Você pode experimentar o Silver Searcher (Ag) ou ripgrep (rg).
user31389
62
grep -r --exclude-dir=dev --exclude-dir=sys --exclude-dir=proc PATTERN data

Fonte: https://stackoverflow.com/questions/2799246/grep-excluding-a-specific-folder-using

Henrik
fonte
17
Observe que isso exclui recursivamente. ./devserá excluído junto com ./foo/bar/dev. Use --exclude-dir=./devpara aplicar apenas ao primeiro caso.
Cory Walker
4
Você também pode encurtar um pouco o globbing: bash grep -r --exclude-dir={dev,sys,proc} PATTERN data O único problema com o globbing é que não consigo fazê-lo funcionar no meu bash. Nesse caso, tenho que mantê-los separados.
b01
3
Observe também que {} funciona apenas se você colocar mais de 1 entradas, o que significa --exclude-dir = {home, .svn} é funciona, mas --exclude-dir = {. Svn} não funciona. Perdi meu tempo para descobrir por que {} não funciona porque eu testei com 1 entrada em primeiro lugar.
林果皞
Se você usar {}uma única entrada, provavelmente precisará de uma vírgula unária para transformá-la em uma matriz (não sabe como o Bash lida com isso). Em vez de fazer isso, acabei criando um alias em meus .bash_aliases que percorre uma lista de pastas que normalmente sempre desejo excluir, por exemplo, .git, .svn, .hg, .cache e os adiciono por meio de um loop com --exclude-dir $dire expanda essa matriz para o alias grep.
precisa saber é o seguinte
6

você pode usar o find:

find . -not -path "*/.svn*" -not -type d -exec grep -ni "myfunc" {} \; -print

OK, então, um pouco para trás, você obtém os resultados grep primeiro e depois o caminho. Talvez alguém mais tenha uma resposta melhor?

Josh
fonte
3
ok, eu gosto muito disso. é claro que encontrar é muito mais flexível. a única diferença entre a saída é que "grep -Rni" imprimirá o nome do arquivo para cada correspondência, enquanto "find -exec grep" imprimirá o nome do arquivo em uma linha e, em seguida, uma linha para cada correspondência (com o número da linha e o conteúdo da linha) ) usando "grep -Hni" forças o nome do arquivo a ser exibido em cada linha
Gabor
Obrigado por fornecer a única resposta que funcionou para sistemas que são este duro, sem grep --exclude-dir, mas ainda tem que ser trabalhado
Dmitri DB
2

Aqui está um exemplo completo de um script em um dos meus projetos que pode ajudar, eu chamo esse arquivo de "all_source" (marcado como executável) e o coloco no diretório raiz do meu projeto, em seguida, chamo-o como se grep myfunc $(./all_source)a classificação no final do script fosse totalmente opcional.

#!/bin/bash

find . \
    -type d \( \
            -wholename './lib' -o \
            -wholename './vc6' -o \
            -name 'gen' -o \
            -name '.svn' \
            \) -prune -o \
    -type f \( \
            -name '*.h' -o \
            -name '*.cpp' -o \
            -name '*.c' -o \
            -name '*.lua' -o \
            -name '*.*awk' \) -print \
    | sort

Esse script retorna todos os nomes de arquivos no projeto que correspondem *.h, *.cpp, *.c, *.lua, *.*awk, mas não pesquisa em todas as pastas nomeadas .svn e gen, além de ignorar as pastas ./libe ./vc6(mas apenas as que estão diretamente na raiz do projeto). Então, quando você faz grep myfunc $(./all_source)isso, apenas recebe esses arquivos. Você precisará chamar isso a partir do diretório raiz do projeto também.

Mike Nelson
fonte
0

Há também a opção -prune para encontrar:

 find . -path "*/.svn*" -prune -o -not -type d -exec grep -ni "myfunc" {} \; -print
misiu_mp
fonte
0

Você pode tentar fazer isso:

grep -R  "myfunc" . | grep -v path_to_exclude/

Por exemplo: se você não deseja pesquisar o conteúdo nos arquivos de log, faça o seguinte:

grep -R "myfunc" . | grep -v log/
Akshatha
fonte