Comment puis-je utiliser grep pour rechercher plusieurs répertoires non imbriqués?

21

Il peut sembler que je pose la même chose que cette question , mais j'ai des exigences différentes. Voici un exemple de mon système de fichiers:

  • /code/
    • interne/
      • dev /
      • principale/
    • Publique/
      • dev /
      • principale/
      • Libération/
    • outils/

/code/internal/dev/, /code/public/dev/Et /code/tools/contenir des sous - répertoires pour plusieurs projets. Je travaille presque exclusivement dans les branches de développement de /code/internal/et /code/public/, et souvent je veux rechercher une chaîne de texte dans ces répertoires avec /code/tools/(qui n'a pas de branches). Dans ces cas, je dois exécuter trois commandes distinctes:

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

Je voudrais savoir s'il existe une seule commande pour ce faire. Sinon, j'aurais probablement besoin d'écrire un simple script bash.

David Kennedy
la source

Réponses:

38

Vous pouvez concaténer plusieurs chemins à rechercher par grep:

grep -r "some string" /code/internal/dev/ /code/public/dev/ /code/tools/
Artur Szymczak
la source
C'est tellement évident. Pourquoi n'y ai-je pas pensé?!
David Kennedy
En fait, cela génère une erreur, grep: /code/internal/dev/*.cs: No such file or directorysauf si je supprime le *.csde la commande. C'est ma faute parce que j'ai posé *.csma question à l'origine.
David Kennedy
14

Si vous souhaitez utiliser au maximum les caractères génériques (et que la hiérarchie que vous avez publiée est complète), vous pouvez le faire

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

Explication:

La première étape effectuée est l'expansion de la liste contreventée. foo{bar,baz}quxse développe à foobarqux foobazqux. Autrement dit, il y a un mot distinct généré pour chaque élément séparé par des virgules dans la liste, avec la partie préfixe et postfixe attachée à chacun. Vous pouvez voir comment cela fonctionne en faisant

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

qui sort

A1B A2B A3B A4B

Notez que cela fonctionne également avec plusieurs accolades et également avec des arguments vides; par exemple

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

donne

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

Donc, après l'expansion de l'accolade, votre commande ressemble à ceci:

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

L'étape suivante est l'expansion des caractères génériques. Vous le savez déjà pour la *.cspartie, mais cela fonctionne aussi pour les répertoires intermédiaires; de plus, si a /suit, seuls les répertoires sont mis en correspondance. Par conséquent, étant donné votre hiérarchie (et la création de noms de .csfichiers pour les fichiers), vous obtiendrez la commande:

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

Ce n'est qu'après que tout cela s'est produit, grepest appelé avec cette liste d'arguments (notez que la même chose se produit avec vos commandes d'origine; grepne voit jamais le *; l'expansion qui est complètement effectuée bashavant d'appeler grep).

celtschk
la source