web-dev-qa-db-fra.com

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

Il peut sembler que je demande 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/ contient 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.

23
Big McLargeHuge

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

grep -r "some string" /code/internal/dev/ /code/public/dev/ /code/tools/
39
Artur Szymczak

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}qux se développe en foobarqux foobazqux. Autrement dit, il existe 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

Ainsi, 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 savez déjà que pour le *.cs part, mais il fonctionne également pour les répertoires intermédiaires; de plus, si un / suit, seuls les répertoires sont mis en correspondance. Par conséquent, étant donné votre hiérarchie (et la création de noms de fichiers pour le .cs 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 tout cela que grep est appelé avec cette liste d'arguments (notez que la même chose se produit avec vos commandes d'origine; grep ne voit jamais le *; l'expansion est entièrement effectuée par bash avant d'appeler grep).

14
celtschk