Rechercher récursivement le dossier mais exclure le sous-dossier svn

10

Je veux trouver toutes les occurrences de foodans un grand système de fichiers géré par SVN mais je ne veux pas faire correspondre quelque chose contenu dans un .svnrépertoire.

J'obtiens des correspondances immédiates quand je le fais, grep -l -e 'foo' *mais quand j'essaie d'exclure les répertoires svn avec grep -l -e 'foo' --exclude-dir=".svn"la commande se bloque simplement.

Qu'est-ce que je fais mal?

Anthony Elliott
la source

Réponses:

11

--exclude-dirne supplante pas la nécessité de lister les fichiers sur la ligne de commande. Vous êtes "suspendu" car grepattend une entrée standard.

grep -l -e 'foo' --exclude-dir = ". svn" *

Pensez à utiliser ack , qui exclut .svnles dossiers similaires et (et possède de nombreuses autres fonctionnalités) par défaut.

éphémère
la source
2
Plus propre si vous passez *à ., au cas où il y aurait d'autres dossiers cachés qui devraient être recherchés.
Kevin
ou peut-être que vous souhaitez utiliser à la --recursive .place, car l'OP a déjà GNU grep.
jw013
Personnellement, je l'ai shopt -s dotglobdans Bash, donc *contient déjà des fichiers dot. -rest sympa, mais le ackfait aussi par défaut :)
éphémère
5

Vous pourriez être intéressé par ack . Il effectue une recherche récursive (et d'autres opérations de type grep) et exclut les répertoires tels que .svn ou .git par défaut.

WhyNotHugo
la source
En guise de suivi, j'utilise actuellement ag, qui est similaire, mais plus rapide.
WhyNotHugo
2

La grep --exclude-dir...solution doit être très bien, mais juste pour montrer une autre façon, vous pouvez le faire avec find« s -prune:

find -name .svn -prune -o -type f -exec grep -l "$pattern" {} +

Si vous voulez exécuter quelque chose de plus, findc'est mieux qu'une simple grep -r:

find -name .svn -prune -o -type f -exec grep -q "$pattern" {} \; -exec ./process {} \;
Kevin
la source
1

Si vous ne voulez pas grep dans des répertoires comme .svn jamais, vous pouvez définir la $GREP_OPTIONSvariable pour l'exclure comme ci-dessous:

export GREP_OPTIONS="--exclude-dir=\*/.svn/\*"

Ajoutez simplement cette ligne à votre .bashrcet vos greps récursifs n'entreront plus dans les .svnrépertoires. Bien sûr, il peut être aussi riche que vous le souhaitez:

export GREP_OPTIONS="--exclude-dir=\*/.svn/\* --exclude-dir=\*/.hg/\* --exclude-dir=\*/.git/\* --exclude=\*~"
brandizzi
la source
1
Personnellement, je fais cela en utilisant un alias afin que je puisse contourner la liste d'exclusion si j'ai besoin de rechercher dans ces dossiers, je peux simplement utiliser grep sans avoir à annuler / annuler la variable. Il me permet également de maintenir une liste de dossiers que je peux facilement développer et ajouter automatiquement à ma liste d'exclusions sans avoir à taper davantage.
dragon788
Voilà une bonne approche. Il a également l'avantage que, si vous avez besoin de grep dans les dossiers, vous n'oublierez pas que vous définissez une variable. (Pas que j'aie jamais eu besoin de les saluer.) Mais TBH ces jours-ci, j'utilise ag (un clone ack) pour ces choses ^^
brandizzi
0

Voici également une solution awk:

find . | awk '$0 !~ /.svn/{print}' | awk '/foo/{print}'

Fondamentalement, à partir de tous les fichiers, élaguez ceux qui correspondent à /.svn/ puis, parmi ceux-ci, imprimez uniquement ceux qui correspondent à / foo /. J'aime aussi cette solution car vous pouvez facilement utiliser les résultats avec ls. Par exemple, vous pouvez utiliser

ls -tl $(find . | awk '$0 !~ /.svn/{print}' | awk '/foo/{print}')

pour voir une vue de liste triée par date de modification. Aussi, c'est bien d'avoir le chemin complet des résultats si vous voulez faire autre chose avec eux (les ouvrir, les exécuter, etc.)

irréléphant
la source