web-dev-qa-db-fra.com

Utilisez la syntaxe grep --exclude / - include pour ne pas passer par grep par le biais de certains fichiers

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

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 souhaite que grep ignore la recherche dans ces fichiers (principalement des images JPEG et PNG). Comment je ferais ça?

Je sais qu'il existe les options --exclude=PATTERN et --include=PATTERN, mais quel est le format du motif? 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 exclure, grep exclude et les variantes n'ont rien trouvé de pertinent

S'il y a un meilleur moyen de grepping que dans certains fichiers, je suis pour. déplacer les fichiers incriminés n'est pas une option. Je ne peux pas rechercher uniquement certains répertoires (la structure des répertoires est un désordre immense, avec tout partout). De plus, je ne peux rien installer, je dois donc utiliser des outils courants (comme grep ou suggéré trouver).

739
Piskvor

Utilisez la syntaxe de globbing du shell:

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

La syntaxe pour --exclude est identique.

Notez que l'étoile est échappée avec une barre oblique inverse pour l'empêcher d'être étendue par le Shell (le citer, comme --include="*.{cpp,h}", fonctionnerait aussi bien). Sinon, si le répertoire de travail en cours contient des fichiers correspondant au modèle, la ligne de commande se développera comme suit: grep pattern -r --include=foo.cpp --include=bar.h rootdir, qui ne recherchera que les fichiers nommés foo.cpp et bar.h, qui est très probablement pas ce que vous vouliez.

718
Adam Rosenfield

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

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

Il effectue une recherche récursive, ignore les fichiers binaires et ne cherche pas dans les dossiers cachés de Subversion, quel que soit le motif que je souhaite. Je l'ai aliasé comme "grepsvn" sur ma boîte au travail.

213
rmeador

S'il vous plaît jeter un oeil à ack , qui est conçu pour exactement ces situations. Votre exemple de

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

est fait avec ack comme

ack -icl "foo="

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

ack -icl --cpp "foo="
63
Andy Lester

grep 2.5.3 a introduit le paramètre --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 seconderai Andy's votera pour ack mais c'est le meilleur.

34
Corey

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

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

La commande suggérée:

grep -Ir --exclude="*\.svn*" "pattern" *

est conceptuellement faux, car --exclude fonctionne sur le nom de base. En d'autres termes, il ignorera uniquement le fichier .svn du répertoire en cours.

12
Nicola

Dans grep 2.5.1, vous devez ajouter cette ligne à ~/.bashrc ou ~/.bash_profile

export GREP_OPTIONS="--exclude=\*.svn\*"
11
deric

Je trouve la sortie de grepping grep très utile parfois:

grep -rn "foo=" . | grep -v "Binary file"

Bien que cela ne l'empêche pas réellement de rechercher les fichiers binaires.

9
Aaron Maenpaa

Sur CentOS 6.6/Grep 2.6.3, je dois l’utiliser comme ceci:

grep "term" -Hnir --include \*.php --exclude-dir "*excluded_dir*"

Notez l'absence de signe égal "=" (sinon --include, --exclude, include-dir et --exclude-dir sont ignorés)

7
aesede

Si vous n'êtes pas opposé à l'utilisation de find, j'aime bien sa fonction -Prune:


find [directory] \
        -name "pattern_to_exclude" -Prune \
     -o -name "another_pattern_to_exclude" -Prune \
     -o -name "pattern_to_INCLUDE" -print0 \
| xargs -0 -I FILENAME grep -IR "pattern" FILENAME

Sur la première ligne, vous spécifiez le répertoire que vous souhaitez rechercher. . (répertoire actuel) est un chemin valide, par exemple.

Sur les 2ème et 3ème lignes, utilisez "*.png", "*.gif", "*.jpg", etc. Utilisez autant de ces constructions -o -name "..." -Prune que vous avez de modèles.

Sur la 4ème ligne, vous avez besoin d'un autre -o (il spécifie "ou" à find), les motifs que vous voulez, et vous avez besoin d'un -print ou -print0 à la fin. . Si vous voulez simplement "tout le reste" qui reste après la taille des images *.gif, *.png, etc., utilisez -o -print0 et vous en avez terminé avec la 4ème ligne.

Enfin, sur la cinquième ligne, se trouve le tuyau vers xargs qui prend chacun des fichiers résultants et les stocke dans une variable FILENAME. Il passe ensuite grep aux drapeaux -IR, au "pattern", puis à FILENAME est développé par xargs pour devenir cette liste de noms de fichiers trouvés par find.

Pour votre question particulière, l'énoncé peut ressembler à quelque chose comme:


find . \
     -name "*.png" -Prune \
     -o -name "*.gif" -Prune \
     -o -name "*.svn" -Prune \
     -o -print0 | xargs -0 -I FILES grep -IR "foo=" FILES
6
OnlineCop

Je suis un dilettante, d'accord, mais voici à quoi ressemble mon ~/.bash_profile:

 export GREP_OPTIONS = "- orl --exclude-dir = .svn --exclude-dir = .cache --color = auto" GREP_COLOR = '1; 32' 

Notez que pour exclure deux répertoires, j'ai dû utiliser --exclude-dir deux fois.

5
4D4M

git grep

Utilisez _git grep_ qui est optimisé pour la performance et vise à rechercher dans certains fichiers.

Par défaut, il ignore les fichiers binaires et respecte votre _.gitignore_. Si vous ne travaillez pas avec la structure Git, vous pouvez toujours l'utiliser en passant _--no-index_.

Exemple de syntaxe:

_git grep --no-index "some_pattern"
_

Pour plus d'exemples, voir:

4
kenorb

Essaye celui-là:

 $ find. -name "* .txt" -type f -print | fichier xargs | grep "foo =" | cut -d: -f1 

Fondée ici: http://www.unix.com/Shell-programming-scripting/42573-search-files-excluding-binary-files.html

3
Gravstar

Si vous effectuez une recherche non récursive, vous pouvez utiliser modèles glop pour faire correspondre les noms de fichiers.

grep "foo" *.{html,txt}

comprend html et txt. Il recherche uniquement dans le répertoire actuel.

Pour rechercher dans les sous-répertoires:

   grep "foo" */*.{html,txt}

Dans les sous-répertoires:

   grep "foo" */*/*.{html,txt}
3
Stéphane Laurent

Regardez @ celui-ci.

grep --exclude="*\.svn*" -rn "foo=" * | grep -v Binary | grep -v tags
2
suhas tawade

ces scripts n'accomplissent pas tout le problème ... Essayez mieux:

du -ha | grep -i -o "\./.*" | grep -v "\.svn\|another_file\|another_folder" | xargs grep -i -n "$1"

ce script est tellement meilleur, car il utilise de "vraies" expressions régulières pour éviter les répertoires de la recherche. il suffit de séparer les noms de dossier ou de fichier avec "\ |" sur le grep -v

profitez-en! trouvé sur mon shell linux! XD

2
villalvilla

Dans les répertoires sont également nombreux fichiers binaires. Je ne peux pas rechercher uniquement certains répertoires (la structure des répertoires est un gros désordre). Y a-t-il une meilleure façon de grepping que dans certains fichiers?

ripgrep

C'est l'un des outils les plus rapides conçus pour rechercher de manière récursive votre répertoire actuel. Il est écrit Rust , construit sur le moteur de regex de Rust pour une efficacité maximale. Vérifiez le analyse détaillée ici .

Donc, vous pouvez juste courir:

rg "some_pattern"

Il respecte votre .gitignore et ignore automatiquement les fichiers/répertoires cachés et les fichiers binaires.

Vous pouvez toujours personnaliser les fichiers et les répertoires d'inclusion ou d'exclusion à l'aide de -g/--glob. Les règles de globalisation correspondent à .gitignore globs. Vérifiez man rg pour obtenir de l'aide.

Pour plus d'exemples, voir: Comment exclure des fichiers ne correspondant pas à certaines extensions avec grep?

Sur macOS, vous pouvez installer via brew install ripgrep.

2
kenorb

find et xargs sont vos amis. Utilisez-les pour filtrer la liste de fichiers plutôt que celle de grep --exclude

Essayez quelque chose comme

find . -not -name '*.png' -o -type f -print | xargs grep -icl "foo="
2
Andrew Stein

approprié pour tcsh fichier .alias:

alias gisrc 'grep -I -r -i --exclude="*\.svn*" --include="*\."{mm,m,h,cc,c} \!* *'

Il m'a fallu un certain temps pour comprendre que la partie {mm, m, h, cc, c} ne devrait PAS être entre guillemets. ~ Keith

1
Keith Knauber

L'option --binary-files=without-match de GNU grep lui permet d'ignorer les fichiers binaires. (Équivalent au commutateur -I mentionné ailleurs.)

(Cela pourrait nécessiter une version récente de grep; 2.5.3 l'a au moins.)

1
mjs

Pour ignorer tous les résultats binaires de grep

grep -Ri "pattern" * | awk '{if($1 != "Binary") print $0}'

La partie awk filtrera toutes les lignes du fichier binaire

0
lathomas64