¿Cómo puedo usar grep para buscar en múltiples directorios no anidados?

21

Puede parecer que estoy haciendo lo mismo que esta pregunta , pero tengo requisitos diferentes. Este es un ejemplo de mi sistema de archivos:

  • /código/
    • interno/
      • dev /
      • principal/
    • público/
      • dev /
      • principal/
      • lanzamiento/
    • herramientas/

/code/internal/dev/, /code/public/dev/Y /code/tools/contener subdirectorios para varios proyectos. Trabajo casi exclusivamente en las ramas de desarrollo de /code/internal/y /code/public/, y a menudo quiero buscar una cadena de texto en esos directorios junto con /code/tools/(que no tiene ramas). En estos casos, tengo que hacer tres comandos separados:

$ grep -r "some string" /code/internal/dev/
$ grep -r "some string" /code/public/dev/
$ grep -r "some string" /code/tools/

Me gustaría saber si hay un solo comando para hacer esto. De lo contrario, lo más probable es que necesite escribir un script bash simple.

David Kennedy
fuente

Respuestas:

38

Puede concatenar varias rutas para que grep busque:

grep -r "some string" /code/internal/dev/ /code/public/dev/ /code/tools/
Artur Szymczak
fuente
Esto es muy obvio. ¿Por qué no pensé en esto?
David Kennedy
En realidad, esto arroja un error a grep: /code/internal/dev/*.cs: No such file or directorymenos que elimine *.csel comando. Esto es mi culpa porque puse el *.csen mi pregunta originalmente.
David Kennedy el
14

Si desea aprovechar al máximo los comodines (y la jerarquía que publicó está completa), puede hacerlo

grep -r "some string" /code/{*/dev,tools}/*.cs

Explicación:

El primer paso realizado es la expansión de la lista de llaves. foo{bar,baz}quxse expande a foobarqux foobazqux. Es decir, se genera una palabra separada para cada elemento separado por comas en la lista, con el prefijo y la parte de postfix adjunta a cada uno. Puedes ver cómo funciona haciendo

echo A{1,2,3,4}B

que salidas

A1B A2B A3B A4B

Tenga en cuenta que esto también funciona con llaves múltiples, y también con argumentos vacíos; por ejemplo

echo {,1,2}{0,1,2}:{2,3}

da

0:2 0:3 1:2 1:3 2:2 2:3 10:2 10:3 11:2 11:3 12:2 12:3 20:2 20:3 21:2 21:3 22:2 22:3

Entonces, después de la expansión de llaves, su comando se ve así:

grep -r "some string" /code/*/dev/*.cs /code/tools/*.cs

El siguiente paso es la expansión de comodines. Ya lo sabe para la *.csparte, pero también funciona para directorios intermedios; además, si a /sigue, solo los directorios coinciden. Por lo tanto, dada su jerarquía (y la composición de los nombres de los .csarchivos), obtendrá el comando:

grep -r "some string" /code/internal/dev/file1.cs /code/internal/dev/file2.cs /code/public/dev/file3.cs /code/tools/file4.cs /code/tools/file5.cs

Solo después de que todo esto haya sucedido, grepse llama con esta lista de argumentos (tenga en cuenta que lo mismo sucede con sus comandos originales; grepnunca llega a ver el *; la expansión se realiza completamente bashantes de llamar grep).

celtschk
fuente