Cómo utilizar el comando "grep" para buscar texto, incluidos subdirectorios

373

Quiero encontrar todos los archivos que contienen una cadena de texto específica. El grepcomando funciona, pero no sé cómo usarlo para cada directorio (solo puedo hacerlo para mi directorio actual). Intenté leer man grep, pero no me sirvió de nada.

Sonrisa cazador
fuente
grep -RIn <yor pattern> * Buscará desde los directorios actuales hacia abajo en todos los archivos de texto. No estoy seguro de cómo hacer mi búsqueda de forma recursiva en patrones de archivo como * .C con solo grep
1
Comodín con --include="*.C"opción, @ user311346, gracias a @Lekensteyn.
Bob Stein
Utilice la combinación de búsqueda y grep para buscar de forma recursiva una cadena en los directorios actuales y en todos los subdirectorios. Mira este wilddiary.com/find-files-containing-my-text
Drona

Respuestas:

487

Sería mejor usar

grep -rl "string" /path

dónde

  • -r(o --recursive) la opción se usa para recorrer también todos los subdirectorios de /path, mientras que
  • -l(o --files-with-matches) la opción se usa para imprimir solo nombres de archivos de archivos coincidentes, y no las líneas coincidentes (esto también podría mejorar la velocidad, dado que grepdeja de leer un archivo en la primera coincidencia con esta opción).
enzotib
fuente
13
En realidad, si "cadena" es un patrón de texto para encontrar, es mejor usar esa funcionalidad, de lo contrario, alguien puede enfrentar problemas cuando la cadena contiene puntos o caracteres especiales que tienen significado en expresiones regulares y no solo un punto que debe encontrarse como una cadena , como es. Luego usaría -rlFinterruptores, -Fpara "cadena fija" (y no regexp, por ejemplo). Por supuesto, si la tarea estaba usando expresiones regulares, entonces discúlpeme. Claro, la misma teoría sin -r también, a menudo veo que las personas asumen grep búsquedas de "texto" y puede causar problemas especiales que significan algo como una expresión regular.
LGB
44
También está la -ibandera que ignora el caso.
Marco Ceppi
3
Solo quisiera mostrar la --recursiveopción, hay muchas opciones y escenarios de uso de los que se puede hablar. Comencé con la respuesta aceptada @dmityugov y modifiqué para trabajar sin ella find.
enzotib
1
@NN: hecho :-)
enzotib
3
@ScottBiggs: con la opción--include '*.h'
enzotib
167

Si está buscando líneas que coincidan en los archivos, mi comando favorito es:

grep -Hrn 'search term' path/to/files
  • -H hace que se imprima el nombre del archivo (implícito cuando se buscan varios archivos)
  • -r hace una búsqueda recursiva
  • -n hace que se imprima el número de línea

path/to/filespuede ser .buscar en el directorio actual

Otras opciones que encuentro muy útiles:

  • -Iignorar archivos binarios (complemento: -atratar todos los archivos como texto)
  • -Ftratar search termcomo un literal, no como una expresión regular
  • -i hacer una búsqueda entre mayúsculas y minúsculas
  • --color=alwayspara forzar los colores incluso al pasar a través less. Para crear lesscolores de soporte, debe usar la -ropción:

    grep -Hrn search . | less -r
    
  • --exclude-dir=dirútil para excluir directorios como .svny .git.

Salida de ejemplo

Lekensteyn
fuente
13
-Hen una carpeta es redundante, si hay más de un archivo, como es probable. De hecho, la página del manual dice-H, --with-filename: Print the file name for each match. This is the default when there is more than one file to search.
enzotib
No lo sabía, siempre funcionó como esperaba. Es mi comando predeterminado cuando busco archivos.
Lekensteyn
1
¿Hay alguna manera de considerar solo archivos con, por ejemplo, una extensión .a (y combinar esto con -r)?
user2413
66
@ user2413 Probar--include '*.*'
Lekensteyn
1
@alper Trygrep --exclude='*~' ...
Lekensteyn
24

Creo que puedes usar algo como esto:

find /path -type f -exec grep -l "string" {} \;

Explicación de comentarios

findes un comando que le permite encontrar archivos y otros objetos como directorios y enlaces en subdirectorios de una ruta determinada. Si no especifica una máscara que los nombres de archivo deben cumplir, enumera todos los objetos de directorio.

  • -type f especifica que solo debe procesar archivos, no directorios, etc.
  • -exec grepespecifica que para cada archivo encontrado, debe ejecutar el comando grep, pasando su nombre de archivo como argumento, reemplazándolo {}por el nombre de archivo
dmityugov
fuente
3
Solo para aquellos que no saben, agregar -name '*.py'restricciones restringe las coincidencias a los archivos que terminan en '.py'.
Daniel F
Me gusta que esto cubra clientes que no tienen -R implementado en su comando grep.
Aviose
Si desea que se imprima la línea coincidente Y el nombre del archivo, haga que el ejecutivo sea como:... -exec bash -c 'grep -r "mystring" {} && echo {}' \;
Donn Lee
¿Cuál es el rendimiento relativo de usar grep directamente?
Jonathan
19

Mi comando predeterminado es

grep -Rin string *

Yo uso un capitol 'R' porque lo lsusa para recursivo. Dado que grep acepta ambos, no hay razón para no usarlo.

EDITAR: por HVNSweeting, aparentemente -Rseguirá enlaces simbólicos donde -rno lo hará.

usuario606723
fuente
1
Para buscar también en archivos ocultos, ejecute shopt -s dotglob(recuerde -scomo "set"). Tenga cuidado al eliminar archivos entonces. Si tiene dotglob habilitado, rm -r *elimina todo en el directorio actual, pero también el directorio que se ..encuentra arriba porque coincide. Para deshabilitar dotglob, use shopt -u dotglob("unset"). Sin embargo, los cambios son temporales, solo se aplica al shell actual.
Lekensteyn
Me olvidé de esto. ¿Hay alguna manera de configurarlo para una línea? algo como shopt -s dotglob & <grep cmd> & shopt -y dotglobsolo más conveniente? De esta manera no tendremos que preocuparnos por restablecerlo
user606723
Además, probablemente sea más fácil de usar grep -Rin string .en la mayoría de estos casos. Solo uso * porque parece ser más natural.
user606723
1
si haces grep recursivo, entonces puedes comenzar desde "." en vez de "*". No se necesita dotglob.
Michał Šrajer
1
votar a esto, una cosa no se menciona en la página de manual está Rva a seguir enlaces simbólicos, rno
HVNSweeting
12

Si estás dispuesto a probar algo nuevo, dale ackuna oportunidad. El comando para buscar recursivamente el directorio actual stringes:

ack string

La instalación es bastante simple:

curl http://betterthangrep.com/ack-standalone > ~/bin/ack && chmod 0755 !#:3

(Siempre que ya tenga el directorio ~/biny esté preferiblemente en su PATH.)

Konrad Rudolph
fuente
2
O simplemente apt-get install ack-grep (y agregue alias ack = ack-grep a su .bashrc)
markijbema
¿Qué hacen los últimos parámetros del chmodcomando? ¿Son específicos chmodo están relacionados con bash (la !#:3parte)?
Elliott Darfink
@ElliottDarfink que utiliza la función de historial de Bash : !es un designador de eventos . Son bastante poderosos para evitar repeticiones. !#:3hace referencia al tercer token de la línea de comando hasta ahora, es decir, ~/bin/acken este caso.
Konrad Rudolph
4

El comando rgrep está dedicado para tal necesidad

Si no está disponible, puede obtenerlo así

mkdir -p ~/bin
cd ~/bin
wget http://sdjf.esmartdesign.com/files/rgrep
chmod +x rgrep

Puede establecer directamente en sus opciones grep predeterminadas como se describe anteriormente.

Yo personalmente uso

[[  ${#args} -lt 5 && "${args//[[:space:]]/}" == "-i" ]] && args="-Hin"
args="${args:--Hns} --color=auto"

tema relacionado: cómo usar siempre rgrep con color

mnono
fuente
rgrep es proporcionado por el paquete grep que se instala por defecto en Ubuntu.
karel
2

Actualización 2:

Esta línea de comandos utiliza findy grepsoluciona el problema:

$ find path_to_search_in -type f -exec grep -in searchString {} 2> /dev/null +

--color=<always or auto> para salida en color:

$ find path_to_search_in -type f \
            -exec grep --color=always -in searchString {} 2>/dev/null +

Ejemplo:

$ find /tmp/test/ -type f -exec grep --color=auto -in "Search string" {} 2>/dev/null +

Un ejemplo se ejecuta en la siguiente instantánea: snap1


Actualización 1:

Puedes probar el siguiente código; como una función en su .bashrco .bash_aliaseso en un script:

wherein () 
{ 
    for i in $(find "$1" -type f 2> /dev/null);
    do
        if grep --color=auto -i "$2" "$i" 2> /dev/null; then
            echo -e "\033[0;32mFound in: $i \033[0m\n";
        fi;
    done
}

Uso: wherein /path/to/search/in/ searchkeyword

ejemplo:

$ wherein ~/Documents/ "hello world"

(Nota: como se sugiere en los comentarios a continuación por @enzotib, esto no funciona con archivos / directorios que incluyen espacios en sus nombres).


Publicación original

Para buscar la cadena y generar solo esa línea con la cadena de búsqueda:

$ for i in $(find /path/of/target/directory -type f); do \
    grep -i "the string to look for" "$i"; done

p.ej:

$ for i in $(find /usr/share/applications -type f); \
    do grep -i "web browser" "$i"; done

Para mostrar el nombre de archivo que contiene la cadena de búsqueda:

$ for i in $(find /path/of/target/directory -type f); do \
    if grep -i "the string to look for" "$i" > /dev/null; then echo "$i"; fi; done;

p.ej:

$ for i in $(find /usr/share/applications -type f); \
    do if grep -i "web browser" "$i" > /dev/null; then echo "$i"; \
    fi; done;
preciso
fuente
Falla en los nombres de archivo que contienen espacios. El error se oculta por el hecho de que stderr no se muestra.
enzotib
@enzotib gracias por señalarlo .. eso es aún sin resolver para la función especificada .. ¡Tengo otra de una sola línea, aunque ..
precisa
Ahora la respuesta es similar a la de @dmityugov.
enzotib
sí, pero en ese sentido, la mayoría de las respuestas en esta página si marca son similares en cuanto al uso que usan grep, además de ser el subconjunto que usa findcon grep... pero si debe aceptar diferentes interruptores y ajustes como una respuesta distinta, probablemente el mío también encajará aquí ... ¿o difieres? la última actualización hace lo que me gustaría en mi búsqueda: nombres de archivo con líneas con clave de búsqueda y número de línea. también :) y salida de color y filtro de error para una mejor legibilidad ..
precisa
2

grep( GNU o BSD )

Puede usar la grepherramienta para buscar de forma recursiva la carpeta actual con -rparámetros, como:

grep -r "pattern" .

Nota: -r- Recursivamente busca subdirectorios.

Para buscar dentro de archivos específicos, puede usar una sintaxis global como:

grep "class foo" **/*.c

Nota: Al usar la opción global ( **), escanea todos los archivos de forma recursiva con una extensión o patrón específico. Para habilitar esta sintaxis, ejecute: shopt -s globstar. También puede usarlo **/*.*para todos los archivos (excepto los ocultos y sin extensión) o cualquier otro patrón.

Si tiene el error de que su argumento es demasiado largo, considere reducir su búsqueda, o use una findsintaxis en su lugar como:

find . -name "*.php" -execdir grep -nH --color=auto foo {} ';'

Alternativamente uso ripgrep.

ripgrep

Si está trabajando en proyectos más grandes o archivos grandes, debe usarlos ripgrep, como:

rg "pattern" .

Consulte los documentos, los pasos de instalación o el código fuente en la página del proyecto GitHub .

Es mucho más rápido que cualquier otra herramienta como GNU / BSD grep , ucg, ag, sift, ack, pto similares, ya que se construye en la parte superior del motor de expresiones regulares de Rust que utiliza autómatas finitos, SIMD y optimizaciones literales agresivas para que la búsqueda sea muy rápido.

Es compatible con los patrones de ignorar especificados en los .gitignorearchivos, por lo que una sola ruta de archivo se puede comparar con múltiples patrones globales simultáneamente.


Puede usar los parámetros comunes como:

  • -i - Búsqueda insensible.
  • -I - Ignorar los archivos binarios.
  • -w - Buscar las palabras completas (en oposición a la coincidencia parcial de palabras).
  • -n - Muestra la línea de tu partido.
  • -C/ --context(p -C5. ej. ): aumenta el contexto para que vea el código circundante.
  • --color=auto - Marcar el texto correspondiente.
  • -H - Muestra el nombre del archivo donde se encuentra el texto.
  • -c- Muestra el recuento de líneas coincidentes. Se puede combinar con -H.
kenorb
fuente
1

Hago esto usando xargs, un comando muy subestimado

find ./ -type f -print0 | xargs -0 grep 'string_you_are_looking_for'

find ./ le brinda una lista recursiva de todos los archivos en una carpeta actual y luego la canaliza a xargs que ejecuta el comando grep en cada uno de esos archivos

programador muerto
fuente
44
El uso xargssin -print0opción findy -0opción a xargsestá en desuso, fallará en los nombres de archivo que contienen espacios.
enzotib
@enzotib He editado la respuesta como usted sugirió. Por favor, revise y si es necesario editar y corregir, me complacerá volver a editar. gracias
αғsнιη
1
@KasiyA: está bien ahora, eliminé mi voto negativo.
enzotib
0

Sé que hay muchas respuestas aquí, pero aquí hay una alternativa si desea agregar otras restricciones al buscar los archivos:

find . -type f -exec grep --quiet string_to_look_for {} ';' -print

Esto funciona porque grepdevolverá 0 si encuentra un resultado, 1 de lo contrario. Por ejemplo, puede encontrar archivos de 1 MB de tamaño y que contengan algo:

find . -type f -exec grep --quiet string_to_look_for {} ';' -size 1M -print

Para múltiples requisitos, probablemente desee utilizar el indicador de optimizador -Oque existe en GNU grep.

Ztyx
fuente
0

Un script (buscar en el código) para buscar en C, código CPP:

#!/bin/sh

find . \( -iname "*.c" -o -iname "*.cpp" -o -iname "*.h" \) -type f -print0 | xargs -0 grep --color -n "$1"

Utilizar:

find-in-code "search string"
nvd
fuente