916 votes

Utilisez la syntaxe grep --exclude/--include pour ne pas parcourir certains fichiers.

Je cherche la chaîne foo= dans des fichiers texte dans une arborescence de répertoires. C'est sur une machine Linux commune, j'ai le shell bash :

grep -ircl "foo=" *

Dans les répertoires se trouvent également de nombreux fichiers binaires qui correspondent à "foo=" . Comme ces résultats ne sont pas pertinents et ralentissent la recherche, je veux que grep saute la recherche de ces fichiers (principalement des images JPEG et PNG). Comment dois-je procéder ?

Je sais qu'il y a les --exclude=PATTERN y --include=PATTERN mais quel est le format du modèle ? La page de manuel de grep dit :

--include=PATTERN     Recurse in directories only searching file matching PATTERN.
--exclude=PATTERN     Recurse in directories skip file matching PATTERN.

Recherche sur grep include , grep include exclude , grep exclude et les variantes n'ont rien trouvé de pertinent

S'il existe un meilleur moyen de n'effectuer des recherches que dans certains fichiers, je suis tout à fait d'accord ; déplacer les fichiers incriminés n'est pas une option. Je ne peux pas rechercher uniquement dans certains répertoires (la structure des répertoires est un grand désordre, avec tout partout). De plus, je ne peux rien installer, je dois donc me contenter d'outils courants (tels que grep ou la proposition trouver ).

14 votes

Juste pour info, les arguments utilisés : -c compte les correspondances dans le fichier -i insensible à la casse -l affiche uniquement les fichiers correspondants -r récursif

73 votes

Un moyen plus rapide d'exclure les répertoires svn est le suivant --exclude-dir=.svn donc grep n'y entre pas du tout.

26 votes

Quelques points pédants à connaître : 1. Notez l'absence de guillemets autour du glob ici : --exclude=' .{png,jpg}' ne fonctionne pas (du moins avec ma version de GNU grep) car grep ne supporte pas {} dans ses globs. Ce qui précède est étendu par l'interpréteur de commandes à '--exclude= .png --exclude=*.jpg' (en supposant qu'aucun fichier ne corresponde dans le cwd - ce qui est hautement improbable puisque vous ne commencez normalement pas les noms de fichiers avec '--exclude='), ce que grep apprécie parfaitement. 2. --exclude est une extension GNU et ne fait pas partie de la définition POSIX de grep, donc si vous écrivez des scripts l'utilisant, sachez qu'ils ne fonctionneront pas nécessairement sur des systèmes non-GNU.

928voto

Adam Rosenfield Points 176408

Utiliser le shell syntaxe de globbing :

grep pattern -r --include=\*.cpp --include=\*.h rootdir

La syntaxe pour --exclude est identique.

Notez que l'étoile est échappée par une barre oblique inverse pour éviter qu'elle ne soit développée par l'interpréteur de commandes (en la citant, comme dans --include="*.cpp" fonctionnerait tout aussi bien). Sinon, si vous avez des fichiers dans le répertoire de travail actuel qui correspondent au motif, la ligne de commande se développera comme suit grep pattern -r --include=foo.cpp --include=bar.cpp rootdir qui ne rechercherait que les fichiers nommés foo.cpp y bar.cpp ce qui n'est probablement pas ce que vous vouliez.

Mise à jour 2021-03-04

J'ai modifié la réponse originale pour supprimer l'utilisation de l'option expansion de l'armature Il s'agit d'une fonctionnalité fournie par plusieurs shells tels que Bash et zsh pour simplifier les schémas de ce type ; mais notez que l'expansion des accolades n'est pas compatible avec les shells POSIX.

L'exemple original était :

grep pattern -r --include=\*.{cpp,h} rootdir

pour rechercher dans tous les .cpp y .h fichiers enracinés dans le répertoire rootdir .

12 votes

Je ne sais pas pourquoi, mais j'ai dû citer le modèle d'inclusion comme ceci : grep pattern -r --include="*.{cpp,h}" rootdir

6 votes

@topek : Bon point -- si vous avez des fichiers .cpp/.h dans votre répertoire courant, alors l'interpréteur de commandes développera le glob avant d'invoquer grep, et vous vous retrouverez avec une ligne de commande du type grep pattern -r --include=foo.cpp --include=bar.h rootdir qui recherchera uniquement les fichiers nommés foo.cpp o bar.h . Si vous n'avez aucun fichier correspondant au glob dans le répertoire actuel, l'interpréteur de commandes transmet le glob à grep, qui l'interprète correctement.

7 votes

Je viens de réaliser que le glob est utilisé pour ne faire correspondre que le nom du fichier. Pour exclure un répertoire entier, il faut --exclude-dir option. Les mêmes règles s'appliquent cependant. Seul le nom de fichier du répertoire est pris en compte, pas le chemin.

235voto

rmeador Points 15107

Si vous voulez simplement ignorer les fichiers binaires, je vous suggère de regarder la méthode -I (i majuscule) option. Il ignore les fichiers binaires. J'utilise régulièrement la commande suivante :

grep -rI --exclude-dir="\.svn" "pattern" *

Il recherche de manière récursive, ignore les fichiers binaires, et ne regarde pas dans les dossiers cachés de Subversion, pour n'importe quel motif que je veux. Je l'ai aliasé "grepsvn" sur ma boîte au travail.

27 votes

--exclude-dir n'est pas disponible partout. Ma boîte RH au travail avec GNU grep 2.5.1 ne l'a pas.

0 votes

Des suggestions sur ce qu'il faut utiliser quand --exclude-dir est indisponible ? Dans toutes mes tentatives, --exclude ne semble pas faire l'affaire.

0 votes

Vous pouvez toujours télécharger la dernière version des sources de grep depuis GNU, et faire un 'configure ; make ; sudo make install'. C'est l'une des premières choses que je fais sur un Mac ou une ancienne distribution Linunx.

73voto

Andy Lester Points 34051

Veuillez jeter un coup d'œil à ack qui est conçu exactement pour ces situations. Votre exemple de

grep -ircl --exclude=*.{png,jpg} "foo=" *

est fait avec ack comme

ack -icl "foo="

car ack ne regarde jamais dans les fichiers binaires par défaut, et -r est activé par défaut. Et si vous ne voulez que les fichiers CPP et H, alors faites simplement

ack -icl --cpp "foo="

0 votes

C'est bien, j'essaierai la version autonome en Perl la prochaine fois, merci.

5 votes

Bien vu, je ne peux plus vivre sans ack.

1 votes

stackoverflow.com/questions/667471/ - Cela vous permettra d'obtenir ack sous Windows, si c'est à partir de là que vous exécutez grep.

37voto

Corey Points 319

Grep 2.5.3 a introduit l'option --exclude-dir qui fonctionnera comme vous le souhaitez.

grep -rI --exclude-dir=\.svn PATTERN .

Vous pouvez également définir une variable d'environnement : GREP_OPTIONS="--exclude-dir=\.svn"

Je suis d'accord. Andy's voter pour ack cependant, c'est le meilleur.

7 votes

+1 pour avoir mentionné le numéro de version exact ; j'ai grep 2.5.1 et l'option exclude-dir n'est pas disponible

32voto

Rushabh Mehta Points 310

J'ai trouvé cela après un long moment, vous pouvez ajouter plusieurs inclusions et exclusions comme :

grep "z-index" . --include=*.js --exclude=*js/lib/* --exclude=*.min.js

6 votes

Il est préférable de les combiner dans une liste comme : --exclude={pattern1,pattern2,pattern3}

0 votes

Assurez-vous que vous ajoutez le --include/s avant tout --exclude/s

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X