grep récursif: exclure des répertoires spécifiques

49

J'utilise beaucoup grep récursif pour trouver des fichiers source avec un contenu spécifique.

grep -Rni "myfunc" .

Sur de grandes bases de code, cela peut être lent, alors j'utilise --incldue pour restreindre les extensions / liste blanche.

grep -Rni --include=*.java "myfunc" .

Cependant, il serait plus efficace d'exclure (d'élaguer) des sous-répertoires entiers, je pense:

grep -Rni --exclude=/.svn/ "myfunc" .

Mais --exclude ne prend en charge que les modèles de fichiers tels que * .java ci-dessus. Comment puis-je exclure des répertoires?

gabor
la source

Réponses:

10

Vous pourriez regarder dans ACK .

Je viens tout juste de commencer à l'utiliser, mais cela semble bien adapté à cela.

Alex Feinman
la source
Ack a l'air plutôt bien. bien que cela exclut intuitivement les fichiers indésirables. l'option --nogroup donne une sortie similaire à grep -Rni
gabor
2
Ack est un peu lent. Vous pouvez essayer The Silver Searcher (Ag) ou ripgrep (rg).
user31389
62
grep -r --exclude-dir=dev --exclude-dir=sys --exclude-dir=proc PATTERN data

Source: https://stackoverflow.com/questions/2799246/grep-excluding-a-specific-folder-using

Henrik
la source
17
Notez que cela exclut récursivement. ./devseront exclus le long de ./foo/bar/dev. Utiliser --exclude-dir=./devpour ne s'appliquer qu'au premier cas.
Cory Walker
4
Vous pouvez aussi raccourcir un peu le processus en effectuant un déplacement: bash grep -r --exclude-dir={dev,sys,proc} PATTERN data Le seul problème avec le déplacement est que je ne parviens pas à le faire fonctionner pendant mon bash. Dans ce cas, je dois les garder séparés.
b01
3
Notez également que {} ne fonctionne que si vous mettez plus de 1 entrées, ce qui signifie que --exclude-dir = {home, .svn} fonctionne, mais --exclude-dir = {. Svn} ne fonctionnera pas. Cela me fait perdre mon temps à comprendre pourquoi {} ne fonctionne pas parce que je teste avec 1 entrée en premier lieu.
林果皞
Si vous utilisez {}une seule entrée, vous aurez probablement besoin d'une virgule unaire pour en faire un tableau (vous ne savez pas comment Bash s'en occupe). Au lieu de cela, j'ai fini par créer un alias dans mon .bash_aliases qui parcourt une liste de dossiers que je veux toujours exclure, par exemple .git, .svn, .hg, .cache, puis je les ajoute via une boucle avec --exclude-dir $dirpuis développez ce tableau dans l'alias grep.
dragon788
6

vous pouvez utiliser find à la place:

find . -not -path "*/.svn*" -not -type d -exec grep -ni "myfunc" {} \; -print

OK, donc c'est un peu en arrière, vous obtenez les résultats de grep en premier, puis le chemin. Peut-être que quelqu'un d'autre a une meilleure réponse?

Josh
la source
3
ok, j'aime ça beaucoup. bien sûr, trouver est beaucoup plus flexible. la seule différence entre les résultats est que "grep -Rni" imprimera le nom du fichier pour chaque correspondance, alors que "find -exec grep" imprimera le nom du fichier sur une ligne, puis sur une ligne pour chaque correspondance (avec le numéro et le contenu de la ligne). ). en utilisant "grep -Hni" force le nom de fichier à être affiché sur chaque ligne
gabor
Merci de fournir la seule réponse qui a fonctionné pour les systèmes croustillants, sans grep --exclude-dir, mais qui doivent encore être travaillés
Dmitri DB
2

Voici un exemple complet d'un script de l'un de mes projets qui pourrait aider. J'appelle ce fichier "all_source" (marqué comme exécutable) et le mets dans le répertoire racine de mon projet, puis je l'appelle comme si grep myfunc $(./all_source)la sorte à la fin du script était totalement optionnel.

#!/bin/bash

find . \
    -type d \( \
            -wholename './lib' -o \
            -wholename './vc6' -o \
            -name 'gen' -o \
            -name '.svn' \
            \) -prune -o \
    -type f \( \
            -name '*.h' -o \
            -name '*.cpp' -o \
            -name '*.c' -o \
            -name '*.lua' -o \
            -name '*.*awk' \) -print \
    | sort

Ce script renvoie tous les noms de fichiers du projet qui correspondent *.h, *.cpp, *.c, *.lua, *.*awk, mais ne recherche pas dans tous les dossiers nommés .svn et gen, ni ignore les dossiers pour ./libet ./vc6(mais uniquement ceux situés à la racine du projet). Ainsi, lorsque vous le faites, vous ne faites grep myfunc $(./all_source)que des greps dans ces fichiers. Vous devrez également appeler cela à partir du répertoire racine du projet.

Mike Nelson
la source
0

Il y a aussi l'option -prune pour trouver:

 find . -path "*/.svn*" -prune -o -not -type d -exec grep -ni "myfunc" {} \; -print
misiu_mp
la source
0

Vous pouvez essayer de faire ceci:

grep -R  "myfunc" . | grep -v path_to_exclude/

Exemple: si vous ne souhaitez pas rechercher le contenu dans les fichiers journaux, procédez comme suit:

grep -R "myfunc" . | grep -v log/
Akshatha
la source