¿Cómo puedo excluir directorios de grep -R?

670

Quiero recorrer todos los subdirectorios, excepto el directorio "node_modules".

TIMEX
fuente
14
Simplemente escriba "man grep" y verá --excluir, y --exclude-dir opciones listadas allí - desde el encabezado de esta pregunta, supongo que ya sabía sobre grep ...
arcseldon
35
Si está buscando código en un repositorio git y node_modulesestá en su .gitignore, git grep "STUFF"es la forma más fácil. git grepbusca los archivos rastreados en el árbol de trabajo, ignorando todo desde.gitignore
0xcaff
2
Un ejemplo para el nodo: grep -R --exclude-dir={node_modules,bower_components} "MyString" | cut -c1-"$COLUMNS"- además, siempre puede alias esto en el shell para 'nodegrep' o lo que sea y usar un argumento de comando como entrada de cadena ...
bshea

Respuestas:

395

SOLUCIÓN 1 (combinar findy grep)

El propósito de esta solución no es tratar con el greprendimiento, sino mostrar una solución portátil: también debería funcionar con busybox o versión GNU anterior a 2.5.

Uso find, para excluir directorios foo y bar:

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

Luego combine findy el uso no recursivo de grep, como una solución portátil:

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

SOLUCIÓN 2 (uso recursivo de grep):

Ya conoces esta solución, pero la agrego ya que es la solución más reciente y eficiente. Tenga en cuenta que esta es una solución menos portátil pero más legible para los humanos.

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

Para excluir múltiples directorios, use --exclude-dircomo:

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

SOLUCIÓN 3 (Ag)

Si busca con frecuencia el código, Ag (The Silver Searcher) es una alternativa mucho más rápida que grep, que está personalizada para buscar código. Por ejemplo, no tiene en cuenta automáticamente los archivos y directorios que aparecen en .gitignore, por lo que no tiene que seguir pasando el mismo engorroso Opciones exclude a grepo find.

hornetbzz
fuente
2
esta combinación busca más rápido que --exclude-dir=diry muestra resultados con colores - fácil de leer
Maxim Yefremov
27
"Esta combinación" find ... -execno es más rápida que grep --exclude-dirpara mí. Gran ventaja para grep (aproximadamente cinco veces más rápido con 26k + archivos, filtrados de 38k + en un HDD), a menos que reemplace el \;con +el combo find / exec. Entonces grep es "solo" aproximadamente un 30% más rápido. La sintaxis grep también es humanamente legible :).
Kjell Andreassen
De acuerdo, ya que esto es obvio. Algunos busyboxes no tienen el comando GREP.
hornetbzz
10
También señala que puede excluir múltiples con--exclude-dir={dir1,dir2}
suh
44
No me sorprende en lo más mínimo ese node_moduleses el ejemplo canónico.
pdoherty926
984

Las versiones recientes de GNU Grep (> = 2.5.2 ) proporcionan:

--exclude-dir=dir

que excluye los directorios que coinciden con el patrón dirde las búsquedas recursivas de directorios.

Entonces puedes hacer:

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

Para obtener más información sobre la sintaxis y el uso, consulte

Para GNU Greps más antiguos y POSIX Grep , use findcomo se sugiere en otras respuestas.

¡O simplemente use ack( Editar : o The Silver Searcher ) y termine!

Johnsyweb
fuente
44
@Manocho: ¡Si crees que ackes genial, prueba The Silver Searcher y ve cómo aumenta la velocidad!
Johnsyweb
30
Sintaxis para los impacientes: --exclude-dir=dirutiliza greplos patrones de expresión regular de los archivos , no el bloqueo de archivos de shell. Los patrones funcionan en rutas relativas a su directorio actual. Así que usa el patrón --exclude-dir=dir, no --exclude-dir="/root/dir/*".
Tanius
15
Si desea excluir múltiples directorios de la búsqueda, ¿hay una mejor opción que usar $ grep -r --exclude-dir=dir1 --exclude-dir=dir2 "string" /path/to/search/dir:?
Darshan Chaudhary
44
Probablemente pasé demasiado tiempo en esto que cualquier persona en su sano juicio, pero por mi vida no puedo descubrir cómo excluir un subdirectorio de la búsqueda, grep -r --exclude-dir=public keyword .funciona, pero grep -r --exclude-dir='public/dist' keyword .no lo hace. Intenté agregar comodines regex, caracteres de escape, etc., pero nada parece ayudar.
dkobozev el
73
Exclusión de varios directorios, así:grep -r "Request" . --exclude-dir={node_modules,git,build}
maverick97
78

Si desea excluir varios directorios :

"r" para recursivo, "l" para imprimir solo los nombres de los archivos que contienen coincidencias e "i" para ignorar las distinciones entre mayúsculas y minúsculas:

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

Ejemplo: quiero encontrar archivos que contengan la palabra 'hola'. Quiero buscar en todos mis directorios de Linux excepto directorio proc , el directorio de arranque , el directorio sys y el directorio raíz :

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

Nota: el ejemplo anterior debe ser root

Nota 2 (según @skplunkerin): no agregue espacios después de las comas en {dir1,dir2,dir3}

Azodio
fuente
55
NOTA: no agregue espacios después de las comas en{dir1,dir2,dir3}
skplunkerin
Gracias, útil cuando se trabaja en el espacio de trabajo SVN:grep -Irsn --exclude-dir=.svn 'foo' .
RAM237
1
Solo puede proporcionar la --exclude-diropción varias veces.
Walf
45

Esta sintaxis

--exclude-dir={dir1,dir2}

se expande por el shell (por ejemplo, Bash), no por grep, en esto:

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

Las citas evitarán que el shell lo expanda, así que esto no funcionará:

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

Los patrones utilizados con --exclude-dirson el mismo tipo de patrones descritos en la página del manual para la --excludeopción:

--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.

El shell generalmente intentará expandir dicho patrón en sí mismo, por lo que para evitar esto, debe citarlo:

--exclude-dir='dir?'

Puede usar las llaves y los patrones de exclusión entre comillas de la siguiente manera:

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

Un patrón puede abarcar múltiples segmentos de ruta:

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

Esto excluiría un directorio como topdir/something/else.

Derek Veit
fuente
14

Use esto con frecuencia:

grepse puede usar junto con -r(recursivo), i(ignorar mayúsculas y minúsculas) y -o(imprime solo una parte coincidente de las líneas). Para excluir el filesuso --excludey para excluir el uso de directorios --exclude-dir.

Al unirlo, terminas con algo como:

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

Describirlo hace que parezca mucho más complicado de lo que realmente es. Más fácil de ilustrar con un ejemplo simple.

Ejemplo:

Supongamos que estoy buscando el proyecto actual para todos los lugares donde establezco explícitamente el valor de la cadena debugger durante una sesión de depuración, y ahora deseo revisar / eliminar.

Escribo un script llamado findDebugger.shy lo uso greppara encontrar todas las ocurrencias. Sin embargo:

Para las exclusiones de archivos: deseo asegurarme de que .eslintrcse ignore (esto en realidad tiene una regla de alineación, por debuggerlo que debe excluirse). Del mismo modo, no quiero que se haga referencia a mi propio script en ningún resultado.

Para exclusiones de directorio: deseo excluir node_modulesya que contiene muchas bibliotecas que hacen referencia debuggery no estoy interesado en esos resultados. También acabo desea omitir .ideay .gitdirectorios ocultos porque no se preocupan por esos lugares de búsqueda tampoco, y desea mantener el performant búsqueda.

Así que aquí está el resultado: creo un script llamado findDebugger.shcon:

#!/usr/bin/env bash
grep -rio --exclude={.eslintrc,findDebugger.sh} \
--exclude-dir={node_modules,.idea,.git} debugger .
arcseldon
fuente
Creo que la opción "r" debería imprimirse con mayúscula "-R".
hornetbzz
1
Interesante. "r" siempre me ha funcionado en nix y mac.
arcseldon
Cuando escribí mi respuesta , solía -R(no recuerdo por qué ahora). Me suelen utilizar -r. Resulta que la versión en mayúscula sigue enlaces simbólicos . TIL
Johnsyweb
@Johnsyweb - gracias. votó por su respuesta - no recuerdo cuándo, probablemente en 2016 cuando agregué esta :)
arcseldon
10

Podrías intentar algo como grep -R search . | grep -v '^node_modules/.*'

Dip switch
fuente
34
No es una buena solución en algunos casos. Por ejemplo: si el directorio 'node_modules' es enorme con muchas coincidencias falsas positivas (de ahí la necesidad de filtrar el directorio), el primer grep está perdiendo mucho tiempo buscando en un subdirectorio y ENTONCES el segundo filtrado grep fuera de los partidos. Es más rápido excluir node_modules en el primer grep.
GuruM
2
no me importa la lentitud, puedo mirar el comando y saber lo que hace
Funkodebat
1
Lo mismo para el comentario de Guru. Un montón de /varcuelga cuando golpea /var/runen mi caso. De ahí la razón por la que quiero evitar el directorio en primer lugar.
jww
3
--exclude-dires la mejor solución a partir de 2016.
Omar Tariq
10

Si está buscando código en un repositorio git y node_modulesestá en su .gitignore, puede usarlo git grep. git grepbusca los archivos rastreados en el árbol de trabajo, ignorando todo, desde.gitignore

git grep "STUFF"
0xcaff
fuente
Este es un consejo muy útil. Gracias.
NKM
4

Muy útil, especialmente para aquellos que tratan con Node.js donde queremos evitar buscar dentro de "node_modules":

find ./ -not -path "*/node_modules/*" -name "*.js" | xargs grep keyword
Néstor Urquiza
fuente
2

Un simple comando de trabajo:

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

Arriba busco el texto "creativecommons.org" en el directorio actual "dspace" y excluyo los directorios {log, assetstore}.

Hecho.

Estiércol
fuente
Aseado, incluidos varios directorios entre paréntesis
Mijo
2

Aquí se han dado muchas respuestas correctas, pero estoy agregando esta para enfatizar un punto que causó que algunos intentos apresurados fallaran antes: exclude-dirtoma un patrón , no una ruta a un directorio.

Digamos que su búsqueda es:

grep -r myobject

Y observa que su salida está abarrotada de resultados de src/other/objects-folder. Este comando no le dará el resultado deseado:

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

¡Y te preguntarás por qué exclude-dirno funciona! Para excluir realmente los resultados del objects-folder, simplemente haga esto:

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

En otras palabras, solo use el nombre de la carpeta , no la ruta. Obvio una vez que lo sabes.

Desde la página del manual:

--exclude-dir = GLOB
Omita cualquier directorio de línea de comandos con un sufijo de nombre que coincida con el patrón GLOB. Al buscar de forma recursiva, omita cualquier subdirectorio cuyo nombre base coincida con GLOB. Ignora las barras diagonales redundantes en GLOB.

Nagev
fuente
2

Esta funciona para mí:

grep <stuff> -R --exclude-dir=<your_dir>
angelo.mastro
fuente
55
¿En qué se diferencia esta respuesta de lo que ya se ha publicado?
aexl
1
find . ! -name "node_modules" -type d 
Jack
fuente
-1

Una forma más simple sería filtrar sus resultados usando "grep -v".

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

Morris
fuente
12
Esta es efectivamente la misma respuesta que DipSwitch proporcionó 3 años antes. Tiene los mismos problemas también.
jww