Como posso excluir diretórios do grep -R?


670

Eu quero atravessar todos os subdiretórios, exceto o diretório "node_modules".



14
Basta digitar "man grep" e você verá as opções --exclude e --exclude-dir listadas ali - no cabeçalho desta pergunta, estou assumindo que você já sabia sobre o grep ...
arcseldon

35
Se você está procurando por código em um repositório git e node_modulesestá no seu .gitignore, git grep "STUFF"é a maneira mais fácil. git greppesquisa os arquivos rastreados na árvore de trabalho, ignorando tudo, desde.gitignore
0xcaff

2
Um exemplo para o nó: grep -R --exclude-dir={node_modules,bower_components} "MyString" | cut -c1-"$COLUMNS"- mais você poderia sempre apelido isso no shell para 'nodegrep' ou o que quer e usar um argumento de comando como entrada para a cadeia ..
bshea

Respostas:


395

SOLUÇÃO 1 (combinar finde grep)

O objetivo desta solução não é lidar com o grepdesempenho, mas mostrar uma solução portátil: também deve funcionar com a versão do busybox ou GNU anterior à 2.5.

Use find, para excluir diretórios foo e bar:

find /dir \( -name foo -prune \) -o \( -name bar -prune \) -o -name "*.sh" -print

Em seguida, combine finde o uso não recursivo de grep, como uma solução portátil:

find /dir \( -name node_modules -prune \) -o -name "*.sh" -exec grep --color -Hn "your text to find" {} 2>/dev/null \;

SOLUÇÃO 2 (uso recursivo de grep):

Você já conhece essa solução, mas eu a adiciono, pois é a solução mais recente e eficiente. Observe que esta é uma solução menos portátil, mas mais legível por humanos.

grep -R --exclude-dir=node_modules 'some pattern' /path/to/search

Para excluir vários diretórios, use --exclude-dircomo:

--exclude-dir={node_modules,dir1,dir2,dir3}

SOLUÇÃO 3 (Ag)

Se você pesquisar com freqüência o código, o Ag (The Silver Searcher) é uma alternativa muito mais rápida ao grep, personalizada para a pesquisa de código. Por exemplo, ele ignora automaticamente os arquivos e diretórios listados em .gitignore, para que você não precise passar as mesmas opções de exclusão complicadas para grepou find.


2
Esta combinação pesquisas mais rápidas do que --exclude-dir=dire mostra resultados com cores - fácil de ler
Maxim Yefremov

27
"essa combinação" find ... -execnão é mais rápida do que grep --exclude-dirpara mim. Vantagem enorme para grep (cerca de cinco vezes mais rápido com 26k + arquivos, filtrados de 38k + em um HDD), a menos que você substituir o \;com +para a descoberta combo / exec. Então o grep é "apenas" cerca de 30% mais rápido. A sintaxe grep também é legível por humanos :).
Kjell Andreassen

Concordo, uma vez que isso é óbvio. Algumas caixas ocupadas não possuem o comando GREP.
Hornetbzz

10
também observando que você pode excluir vários com--exclude-dir={dir1,dir2}
suh

4
Não estou nem um pouco surpreso com node_moduleso exemplo canônico.
precisa saber é o seguinte

984

Versões recentes do GNU Grep (> = 2.5.2 ) fornecem:

--exclude-dir=dir

que exclui diretórios correspondentes ao padrão dirdas pesquisas recursivas de diretório.

Então você pode fazer:

grep -R --exclude-dir=node_modules 'some pattern' /path/to/search

Para um pouco mais de informações sobre sintaxe e uso, consulte

Para GNU Greps mais antigo e POSIX Grep , use findcomo sugerido em outras respostas.

Ou apenas use ack( Edit : ou The Silver Searcher ) e pronto!


4
@Manocho: Se você acha que acké ótimo, tente o Silver Searcher e veja a velocidade aumentar!
Johnsyweb

30
Sintaxe para os impacientes: --exclude-dir=dirusa grepos padrões de expressão regular, não os arquivos do shell. Os padrões funcionam em caminhos relativos ao seu diretório atual. Então use padrão --exclude-dir=dir, não --exclude-dir="/root/dir/*".
tanius

15
Se você deseja excluir vários diretórios da pesquisa, existe uma opção melhor do que usar $ grep -r --exclude-dir=dir1 --exclude-dir=dir2 "string" /path/to/search/dir:?
Darshan Chaudhary

4
Provavelmente gastei muito tempo com isso do que qualquer pessoa sã, mas não consigo descobrir como excluir um subdiretório da pesquisa - grep -r --exclude-dir=public keyword .funciona, mas grep -r --exclude-dir='public/dist' keyword .não funciona. Tentei adicionar caracteres curinga regex, caracteres de escape etc., mas nada parece ajudar.
Dkobozev 6/07

73
Exclua vários diretórios da seguinte maneira:grep -r "Request" . --exclude-dir={node_modules,git,build}
maverick97

78

Se você deseja excluir vários diretórios :

"r" para recursivo, "l" para imprimir apenas nomes de arquivos contendo correspondências e "i" para ignorar distinções entre maiúsculas e minúsculas:

grep -rli --exclude-dir={dir1,dir2,dir3} keyword /path/to/search

Exemplo: quero encontrar arquivos que contenham a palavra 'olá'. Eu quero procurar em todos os meus diretórios linux, exceto diretório proc , diretório de inicialização , diretório sys e diretório raiz :

grep -rli --exclude-dir={proc,boot,root,sys} hello /

Nota: O exemplo acima precisa ser root

Nota 2 (de acordo com @skplunkerin): não adicione espaços após as vírgulas em {dir1,dir2,dir3}


5
NOTA: não adicione espaços após as vírgulas{dir1,dir2,dir3}
skplunkerin

Obrigado, útil ao navegar pela área de trabalho SVN:grep -Irsn --exclude-dir=.svn 'foo' .
RAM237

1
Você pode apenas fornecer a --exclude-diropção várias vezes.
Walf

45

Esta sintaxe

--exclude-dir={dir1,dir2}

é expandido pelo shell (por exemplo, Bash), e não por grep:

--exclude-dir=dir1 --exclude-dir=dir2

A citação impedirá que o shell a expanda, portanto isso não funcionará:

--exclude-dir='{dir1,dir2}'    <-- this won't work

Os padrões usados ​​com --exclude-dirsão os mesmos tipos descritos na página de manual da --excludeopção:

--exclude=GLOB
    Skip files whose base name matches GLOB (using wildcard matching).
    A file-name glob can use *, ?, and [...]  as wildcards, and \ to
    quote a wildcard or backslash character literally.

A concha geralmente tentará expandir esse padrão, portanto, para evitar isso, cite-o:

--exclude-dir='dir?'

Você pode usar os chavetas e os padrões de exclusão entre aspas juntos assim:

--exclude-dir={'dir?','dir??'}

Um padrão pode abranger vários segmentos de caminho:

--exclude-dir='some*/?lse'

Isso excluiria um diretório como topdir/something/else.


14

Use frequentemente isso:

greppode ser usado em conjunto com -r(recursiva), i(ignorar maiúsculas e minúsculas) e -o(imprime apenas parte correspondente das linhas). Para excluir o filesuso --excludee excluir diretórios, use--exclude-dir .

Ao juntá-lo, você acaba com algo como:

grep -rio --exclude={filenames comma separated} \
--exclude-dir={directory names comma separated} <search term> <location>

A descrição faz com que pareça muito mais complicado do que realmente é. Mais fácil de ilustrar com um exemplo simples.

Exemplo:

Suponha que eu esteja procurando pelo projeto atual para todos os locais em que defino explicitamente o valor da string debugger durante uma sessão de depuração e agora desejo revisar / remover.

Eu escrevo um script chamado findDebugger.she usogrep para encontrar todas as ocorrências. Contudo:

Para exclusões de arquivos - desejo garantir que isso .eslintrcseja ignorado (isso realmente tem uma regra de linting sobredebugger exclusão isso, deve ser excluída). Da mesma forma, não quero que meu próprio script seja referenciado em nenhum resultado.

Para exclusões de diretório - desejo excluir node_modules, pois contém muitas bibliotecas que fazem referência debuggere não estou interessado nesses resultados. Também quero omitir .ideae.git escondidos diretórios porque eu não se preocupam com esses locais de pesquisa, quer, e desejo de manter a performance pesquisa.

Então, aqui está o resultado - eu crio um script chamado findDebugger.shcom:

#!/usr/bin/env bash
grep -rio --exclude={.eslintrc,findDebugger.sh} \
--exclude-dir={node_modules,.idea,.git} debugger .

Eu acredito que a opção "r" deve ser impressa com maiúsculas "-R".
### hornetbzz #

1
Interessante. "r" sempre funcionou para mim no nix e no mac.
Arcseldon 13/0318

Quando escrevi minha resposta , usei -R(não me lembro por que agora). Eu normalmente uso -r. Acontece que a versão em maiúscula segue links simbólicos . TIL.
Johnsyweb 21/04

@Johnsyweb - obrigado. votou positivamente sua resposta - não me lembro quando, provavelmente em 2016, quando adicionei essa :) :)
arcseldon 22/04

10

Você poderia tentar algo como grep -R search . | grep -v '^node_modules/.*'


34
Não é uma solução tão boa em alguns casos. Por exemplo: Se o diretório 'node_modules' for enorme, com muitas correspondências falsas positivas (daí a necessidade de filtrar o diretório), o primeiro grep estará perdendo muito tempo pesquisando em um subdiretório e, em seguida, a segunda filtragem grep os jogos. É mais rápido excluir node_modules no primeiro grep.
gurum

2
eu não me importo sobre a lentidão, eu posso olhar para o comando e sabe o que faz
Funkodebat

1
O mesmo vale para o comentário do Guru. Um grep de /vartrava quando bate /var/runno meu caso. Daí a razão pela qual eu quero evitar o diretório em primeiro lugar.
jww 31/08/2015

3
--exclude-diré a melhor solução a partir de 2016.
Omar Tariq

10

Se você está procurando por código em um repositório git e node_modulesestá no seu .gitignore, você pode usá-lo git grep. git greppesquisa os arquivos rastreados na árvore de trabalho, ignorando tudo, desde.gitignore

git grep "STUFF"

Esta é uma dica muito útil.Obrigado.
NKM

4

Muito útil, especialmente para aqueles que lidam com o Node.js, onde queremos evitar pesquisar dentro de "node_modules":

find ./ -not -path "*/node_modules/*" -name "*.js" | xargs grep keyword

2

Um simples comando de trabalho:

root/dspace# grep -r --exclude-dir={log,assetstore} "creativecommons.org"

Acima, escrevo o texto "creativecommons.org" no diretório atual "dspace" e excluo dirs {log, assetstore}.

Feito.


Limpo, incluindo vários diretórios entre parênteses
Mijo 15/11

2

Muitas respostas corretas foram dadas aqui, mas estou adicionando uma para enfatizar um ponto que causou algumas tentativas fracassadas antes: exclude-dirassume um padrão , não um caminho para um diretório.

Diga que sua pesquisa é:

grep -r myobject

E você percebe que sua saída está cheia de resultados do src/other/objects-folder. Este comando não fornecerá o resultado pretendido:

grep -r myobject --exclude-dir=src/other/objects-folder

E você pode se perguntar por que exclude-dirnão está funcionando! Para realmente excluir resultados do objects-folder, basta fazer o seguinte:

grep -r myobject --exclude-dir=objects-folder

Em outras palavras, basta usar o nome da pasta , não o caminho. Óbvio quando você o conhece.

Na página do manual:

--exclude-dir = GLOB Ignora
qualquer diretório da linha de comandos com um sufixo de nome que corresponda ao padrão GLOB. Ao pesquisar recursivamente, pule qualquer subdiretório cujo nome base corresponda ao GLOB. Ignore quaisquer barras redundantes à direita no GLOB.


2

Este funciona para mim:

grep <stuff> -R --exclude-dir=<your_dir>

5
Qual é a diferença desta resposta do que já foi publicado?
Aexl

1
find . ! -name "node_modules" -type d 

-1

Uma maneira mais simples seria filtrar seus resultados usando "grep -v".

grep -i needle -R * | grep -v node_modules


12
Esta é efetivamente a mesma resposta que o DipSwitch forneceu 3 anos antes. Também tem os mesmos problemas.
JWW
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.