Comment est-ce que je grep récursivement?


1682

Comment récursivement greptous les répertoires et sous-répertoires?

find . | xargs grep "texthere" *

110
@ TC1 Ce qui est triste, c'est que grep lui-même peut répondre à la question (au moins GNU grep): grep --help | grep récursif
Frank Schmitt

7
Si vous utilisez fréquemment grep pour effectuer des recherches récursives (en particulier si vous effectuez manuellement de nombreuses exlusions de fichiers / répertoires), vous pouvez trouver ack (une alternative grep très conviviale pour les programmeurs) utile.
Nick McCurdy

19
En fait, ni -r ni - travaux récursifs sur la boîte Solaris que j'utilise au travail. Et la page de manuel de grep ne mentionne rien de récursif. J'ai dû recourir pour trouver et xargs moi-même.
Ben

8
ag est ma façon préférée de le faire maintenant github.com/ggreer/the_silver_searcher
dranxo

1
grep -rin xlsx *.plne fonctionne pas pour moi sur Redhat Linux. J'obtiens une erreur "pas de correspondance".
Bulrush

Réponses:


2507
grep -r "texthere" .

Le premier paramètre représente l'expression régulière à rechercher, tandis que le second représente le répertoire à rechercher. Dans ce cas, .signifie le répertoire courant.

Remarque: Cela fonctionne pour GNU grep, et sur certaines plates-formes comme Solaris, vous devez spécifiquement utiliser GNU grep par opposition à l'implémentation héritée. Pour Solaris, c'est la ggrepcommande.


39
Remarque: "grep -r" ne fonctionne que sur les greps plus récents. Cela ne fonctionne pas sur le grep fourni avec AIX 5.3par exemple.
Retenu le

110
Utilisez grep -R pour suivre les liens symboliques.
Eloff

53
Il est bon de savoir que "-i" le rendrait insensible à la casse, et "-n" inclut également le numéro de ligne pour chaque résultat correspondant.
Sadegh

24
aussi bon à savoir, si vous cherchez juste une chaîne fixe et non une expression régulière, utilisez l'option -F. il vous fera gagner du temps en n'invoquant pas l'analyseur d'expressions rationnelles. très pratique si vous recherchez beaucoup de fichiers.
Jeff

6
alias rgrep = 'grep -r'
totten

679

Si vous connaissez l'extension ou le motif du fichier que vous souhaitez, une autre méthode consiste à utiliser l' --includeoption:

grep -r --include "*.txt" texthere .

Vous pouvez également mentionner les fichiers à exclure --exclude.

Ag

Si vous recherchez fréquemment du code, Ag (The Silver Searcher) est une alternative beaucoup plus rapide à grep, qui est personnalisée pour la recherche de code. Par exemple, il est récursif par défaut et ignore automatiquement les fichiers et répertoires répertoriés dans .gitignore, vous n'avez donc pas à passer les mêmes options d'exclusion lourdes à grep ou find.


3
Fonctionne très bien avec grep fourni avec Linux et Cygwin, mais pas avec celui fourni avec AIX.
Retenu le

1
@KrzysztofWolny: `` au lieu de =fonctionner très bien sur Ubuntu. PS: c'est censé être un espace à contre-courant, mais l'analyseur de démarque SO a échoué.
Dan Dascalescu

4
@DanDascalescu J'ai voté pour grep, pas pour l'Ag, juste pour que vous le sachiez :)
Bernhard

1
Avons-nous une option pour exclure un répertoire lors d'une recherche récursive?
Tom Taylor

Windows cygwin aime les guillemets doubles--include "*.txt" --include "*.TXT"
Bob Stein

127

Aussi:

find ./ -type f -print0 | xargs -0 grep "foo"

mais grep -rc'est une meilleure réponse.


14
Ou si vous ne voulez pas vous soucier des espaces dans les noms de fichiers, cela find . -type f -exec grep "foo" '{}' \;fonctionne bien là où c'est pris en charge.
Edd Steel

4
Si vous allez diriger la recherche via xargs vers grep, ET si vous recherchez uniquement une chaîne fixe (c'est-à-dire, pas une expression régulière), vous pourriez bénéficier de l'invocation de l'option grep -F, afin que grep ne charge pas le moteur d'expression régulière pour chaque invocation. S'il y a beaucoup de fichiers, ce sera beaucoup plus rapide.
Jeff

2
trouver . -type f -exec grep -Hu "foo" {} \; est ce que j'utilise car il donne le nom de fichier.
Wes

Cela fonctionne sur tous les * nix car c'est POSIX 7
Ciro Santilli 郝海东 郝海东 病 六四 事件 法轮功

1
find ./ -type f -print0 | xargs -0 grep "foo"
aehlke

118

J'utilise désormais toujours (même sous Windows avec GoW - Gnu sous Windows ):

grep --include="*.xxx" -nRHI "my Text to grep" *

Cela inclut les options suivantes:

--include=PATTERN

Réexaminez dans les répertoires en recherchant uniquement la correspondance des fichiers PATTERN.

-n, --line-number

Préfixez chaque ligne de sortie avec le numéro de ligne dans son fichier d'entrée.

(Remarque: phuclv ajoute dans les commentaires ce qui -ndiminue considérablement les performances , vous pouvez donc ignorer cette option)

-R, -r, --recursive

Lisez tous les fichiers sous chaque répertoire, récursivement; c'est l'équivalent de l' -d recurseoption.

-H, --with-filename

Imprimez le nom de fichier pour chaque correspondance.

-I     

Traitez un fichier binaire comme s'il ne contenait pas de données correspondantes;
c'est l'équivalent de l' --binary-files=without-matchoption.

Et je peux ajouter ' i' ( -nRHIi), si je veux des résultats insensibles à la casse.

Je peux obtenir:

/home/vonc/gitpoc/passenger/gitlist/github #grep --include="*.php" -nRHI "hidden" *
src/GitList/Application.php:43:            'git.hidden'      => $config->get('git', 'hidden') ? $config->get('git', 'hidden') : array(),
src/GitList/Provider/GitServiceProvider.php:21:            $options['hidden'] = $app['git.hidden'];
tests/InterfaceTest.php:32:        $options['hidden'] = array(self::$tmpdir . '/hiddenrepo');
vendor/klaussilveira/gitter/lib/Gitter/Client.php:20:    protected $hidden;
vendor/klaussilveira/gitter/lib/Gitter/Client.php:170:     * Get hidden repository list
vendor/klaussilveira/gitter/lib/Gitter/Client.php:176:        return $this->hidden;
...

Gow semble prometteur - plus récent que les utilitaires GNU Windows que j'utilise. Essayer maintenant ...
Radim Cernej

quel est le sens du dernier caractère * ici?
lorniper

2
@lorniper fait que le shell sélectionne tous les fichiers et dossiers de votre répertoire actuel, ce qui fait que le grep s'applique à ces fichiers et (récursivement à cause de l' -Roption) aux dossiers.
VonC

2
@lorniper Noy exactement: *ou .est un modèle glob (interprété par le shell): unix.stackexchange.com/a/64695/7490 . ' .' sélectionnera également les fichiers de points ou les dossiers de points (comme .git/)
VonC

auparavant, j'ai toujours utilisé, grep -rnImais j'ai appris que cela -ndiminue beaucoup les performances, donc je ne l'utilise que lorsque c'est vraiment nécessaire et normalement j'utiliserai-rI
phuclv

25

Dans les systèmes POSIX, vous ne trouvez pas de -rparamètre pour grepet votre grep -rn "stuff" .ne fonctionnera pas, mais si vous utilisez la findcommande, il:

find . -type f -exec grep -n "stuff" {} \; -print

Approuvé par Solariset HP-UX.


quel est le sens de {} \; -imprimer respectivement?
user1169587

3
En -execoption - le symbole {}est une référence au nom de fichier actuellement trouvé parfind outil (c'est-à-dire faire quelque chose avec le nom de fichier que nous avons trouvé), également l' -execoption doit être terminée par le ;symbole (pour marquer la fin des commandes exec), mais parce que c'est tout en cours d'exécution dans un shell, ce symbole doit être échappé .. et enfin l' -printoption permet à l' findoutil d'imprimer les noms de fichiers trouvés sur l'écran.
tour

19

globbing **

Utiliser des grep -rœuvres, mais cela peut exagérer, en particulier dans les grands dossiers.

Pour une utilisation plus pratique, voici la syntaxe qui utilise la syntaxe de globalisation ( **):

grep "texthere" **/*.txt

qui ne greps que des fichiers spécifiques avec le modèle sélectionné. Il fonctionne pour les shells pris en charge tels que Bash +4 ou zsh .

Pour activer cette fonction, exécutez: shopt -s globstar.

Voir aussi: Comment trouver tous les fichiers contenant du texte spécifique sur Linux?

git grep

Pour les projets sous contrôle de version Git, utilisez:

git grep "pattern"

ce qui est beaucoup plus rapide.

ripgrep

Pour les grands projets, l'outil de grepping le plus rapide est ripgrep qui récupère les fichiers de manière récursive par défaut:

rg "pattern" .

Il est construit sur le moteur regex de Rust qui utilise des automates finis, SIMD et des optimisations littérales agressives pour rendre la recherche très rapide. Consultez l' analyse détaillée ici .


3
Merci pour la suggestion de git grep - c'est très utile et je ne le savais pas!
Basya

2
Merci pour la suggestion de ripgrep. C'est beaucoup plus rapide.
Qu'est-ce qui serait cool

11

Pour trouver le nom de fileswith pathcontenant récursivement la stringcommande particulière d' utilisation ci-dessous pour UNIX:

find . | xargs grep "searched-string"

pour Linux:

grep -r "searched-string" .

trouver un fichier sur le UNIXserveur

find . -type f -name file_name

trouver un fichier sur le serveur LINUX

find . -name file_name

11

seuls les noms de fichiers peuvent aussi être utiles

grep -r -l "foo" .

10

Si vous souhaitez uniquement suivre les répertoires réels et non les liens symboliques,

grep -r "thingToBeFound" directory

Si vous souhaitez suivre les liens symboliques ainsi que les répertoires réels (attention à la récursion infinie),

grep -R "thing to be found" directory

Puisque vous essayez de grep récursivement, les options suivantes peuvent également vous être utiles:

-H: outputs the filename with the line

-n: outputs the line number in the file

Donc, si vous voulez trouver tous les fichiers contenant Dark Vador dans le répertoire en cours ou n'importe quel sous-répertoire et capturer le nom de fichier et le numéro de ligne, mais ne voulez pas que la récursion suive les liens symboliques, la commande serait

grep -rnH "Darth Vader" .

Si vous souhaitez retrouver toutes les mentions du mot chat dans l'annuaire

/home/adam/Desktop/TomAndJerry 

et vous êtes actuellement dans l'annuaire

/home/adam/Desktop/WorldDominationPlot

et vous voulez capturer le nom de fichier mais pas le numéro de ligne d'une instance de la chaîne "chats", et vous voulez que la récursivité suive les liens symboliques si elle les trouve, vous pouvez exécuter l'une des opérations suivantes

grep -RH "cats" ../TomAndJerry                   #relative directory

grep -RH "cats" /home/adam/Desktop/TomAndJerry   #absolute directory

La source:

exécution de "grep --help"

Une courte introduction aux liens symboliques, pour tous ceux qui lisent cette réponse et confus par ma référence à eux: https://www.nixtutor.com/freebsd/understanding-symbolic-links/


Très bonne réponse. Les commutateurs supplémentaires (-rnh) sont très utiles, donc merci de les suggérer.
semtex41

8

ag est ma façon préférée de le faire maintenant github.com/ggreer/the_silver_searcher . C'est fondamentalement la même chose que ack mais avec quelques optimisations supplémentaires.

Voici une brève référence. J'efface le cache avant chaque test (cf /ubuntu/155768/how-do-i-clean-or-disable-the-memory-cache )

ryan@3G08$ sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3
ryan@3G08$ time grep -r "hey ya" .

real    0m9.458s
user    0m0.368s
sys 0m3.788s
ryan@3G08:$ sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3
ryan@3G08$ time ack-grep "hey ya" .

real    0m6.296s
user    0m0.716s
sys 0m1.056s
ryan@3G08$ sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3
ryan@3G08$ time ag "hey ya" .

real    0m5.641s
user    0m0.356s
sys 0m3.444s
ryan@3G08$ time ag "hey ya" . #test without first clearing cache

real    0m0.154s
user    0m0.224s
sys 0m0.172s


6

Si vous recherchez un contenu spécifique dans tous les fichiers d'une structure de répertoires, vous pouvez utiliser findcar il est plus clair ce que vous faites:

find -type f -exec grep -l "texthere" {} +

Notez que -l(downcase of L) affiche le nom du fichier qui contient le texte. Supprimez-le si vous souhaitez imprimer le match lui-même. Ou utilisez -Hpour obtenir le fichier avec la correspondance. Dans l'ensemble, d'autres alternatives sont:

find -type f -exec grep -Hn "texthere" {} +

-nimprime le numéro de ligne.


2
Up-voté pour être la seule findsolution à la fois éviter l' utilisation inutile xargset utiliser au +lieu de \;avec -exec, évitant ainsi des tonnes de lancements de processus inutiles. :-)
ShadowRanger

6

C'est celui qui a fonctionné pour mon cas sur ma machine actuelle (git bash sur windows 7):

find ./ -type f -iname "*.cs" -print0 | xargs -0 grep "content pattern"

J'oublie toujours les -print0 et -0 pour les chemins avec des espaces.

EDIT: Mon outil préféré est maintenant à la place ripgrep: https://github.com/BurntSushi/ripgrep/releases . C'est vraiment rapide et a de meilleures valeurs par défaut (comme récursif par défaut). Même exemple que ma réponse d'origine mais en utilisant ripgrep:rg -g "*.cs" "content pattern"


4

grep -r "texthere" . (délai de préavis à la fin)

(^ crédit: https://stackoverflow.com/a/1987928/1438029 )


Clarification:

grep -r "texthere" /(grep récursivement tous les répertoires et sous-répertoires)

grep -r "texthere" .(grep récursivement ces répertoires et sous-répertoires)

grep récursif

grep [options] PATTERN [FILE...]

[options]

-R, -r, --recursive

Lisez tous les fichiers sous chaque répertoire, récursivement.

C'est l'équivalent de l' option -d recurseou --directories=recurse.

http://linuxcommand.org/man_pages/grep1.html

aide grep

$ grep --help

$ grep --help |grep recursive
  -r, --recursive           like --directories=recurse
  -R, --dereference-recursive

Alternatives

ack( http://beyondgrep.com/ )

ag( http://github.com/ggreer/the_silver_searcher )


4

En 2018, vous souhaitez utiliser ripgrepou the-silver-searcherparce qu'ils sont beaucoup plus rapides que les alternatives.

Voici un répertoire avec 336 sous-répertoires de premier niveau:

% find . -maxdepth 1 -type d | wc -l
     336

% time rg -w aggs -g '*.py'
...
rg -w aggs -g '*.py'  1.24s user 2.23s system 283% cpu 1.222 total

% time ag -w aggs -G '.*py$'
...
ag -w aggs -G '.*py$'  2.71s user 1.55s system 116% cpu 3.651 total

% time find ./ -type f -name '*.py' | xargs grep -w aggs
...
find ./ -type f -name '*.py'  1.34s user 5.68s system 32% cpu 21.329 total
xargs grep -w aggs  6.65s user 0.49s system 32% cpu 22.164 total

Sur Mac OS X, cela installe ripgrep: brew install ripgrep. Cela installe silver-searcher: brew install the_silver_searcher.


La vitesse est importante si vous devez le faire souvent, mais la plupart d'entre nous ne le faisons que quelques fois par an au maximum. L'installation du dernier outil du jour de juju tiers est exagéré et les solutions qui n'ont pas beaucoup changé depuis 1978 sont bonnes à savoir malgré tout.
tripleee

Je trouve très peu plausible qu'un programmeur ne recherche du texte dans un arbre source que plusieurs fois par an. Mais même du point de vue de l'utilisabilité, rga un avantage considérable sur le bricolage d'une commande récursive grep à partir de zéro. L' utilisation rg: rg foo. L' utilisation d' outils unix: find . | xargs grep foo. Et si l'un de vos fichiers contient un devis, vous devez l'utiliser find . -print0 | xargs -0 grep foo. Allez-vous vous en souvenir si vous l'utilisez plusieurs fois par an?
hughdbrown

1
Vous oubliez find . -type f -exec grep 'regex' {} +ce qui est en effet facile à retenir si vous utilisez régulièrement ces outils. Mais vous devriez probablement exécuter ctagsou etagssur votre arbre source de toute façon si vous avez besoin de trouver des choses fréquemment.
tripleee

J'utilise ripgrep et c'est génial. Mais Silver Searcher est fantastique pour les programmeurs. +1
Matt

3

Dans mon serveur IBM AIX (version du système d'exploitation: AIX 5.2), utilisez:

find ./ -type f -print -exec grep -n -i "stringYouWannaFind" {} \; 

cela affichera le chemin / nom de fichier et le numéro de ligne relatif dans le fichier comme:

./inc/xxxx_x.h

2865: / ** Description: stringYouWannaFind * /

de toute façon, ça marche pour moi :)


3

Vous trouverez ci-dessous la commande de recherche Stringrécursive sur Unixet Linuxenvironnement.

pour la UNIXcommande est:

find . -name "string to be searched" -exec grep "text" "{}" \;

pour la Linuxcommande est:

grep -r "string to be searched" .

2

Pour une liste des drapeaux disponibles:

grep --help 

Renvoie toutes les correspondances pour le texte d' expression rationnelle dans le répertoire courant, avec le numéro de ligne correspondant:

grep -rn "texthere" .

Renvoie toutes les correspondances pour texthere , en commençant par le répertoire racine, avec le numéro de ligne correspondant et en ignorant la casse:

grep -rni "texthere" /

drapeaux utilisés ici:

  • -r récursif
  • -n numéro de ligne d'impression avec sortie
  • -i ignorer la casse

1

Je suppose que c'est ce que vous essayez d'écrire

grep myText $(find .)

et cela peut être quelque chose d'autre utile si vous voulez trouver les fichiers grep hit

grep myText $(find .) | cut -d : -f 1 | sort | uniq

C'est très intuitif: par exemple: grep -i acc $ (find. -Name "execution *. *")
Yu Shen

1

Jeter mes deux cents ici. Comme d'autres l'ont déjà mentionné, grep -r ne fonctionne pas sur toutes les plateformes. Cela peut sembler idiot mais j'utilise toujours git.

git grep "texthere"

Même si le répertoire n'est pas monté, je le mets en scène et j'utilise git grep.


0

Notez que des find . -type f | xargs grep whateversortes de solutions se heurteront aux erreurs "Argument list to long" lorsqu'il y a trop de fichiers correspondant à find.

Le meilleur pari est grep -rmais si ce n'est pas disponible, utilisez find . -type f -exec grep -H whatever {} \;plutôt.


Hein? xargsest spécifiquement une solution de contournement pour le problème «Liste d'arguments trop longue».
tripleee

2
Eh bien, non - xargs est spécifiquement conçu pour convertir un tube d'arguments en une liste d'arglist, mais oui, il est vrai que les xargs modernes lorsqu'ils sont utilisés avec -s et / ou -L peuvent traiter de très longues listes d'arglists en se divisant en plusieurs appels de commandes, mais il n'est pas configuré de cette façon par défaut (et ne figurait dans aucune des réponses ci-dessus). À titre d'exemple:find . -type f | xargs -L 100 grep whatever
m.thome

Sur quelle plateforme serait-ce? POSIXxargs est standardisé pour avoir ce comportement hors de la boîte. "L' xargsutilitaire doit limiter la longueur de la ligne de commande de telle sorte que lorsque la ligne de commande est invoquée, l'argument combiné et les listes d'environnement ... ne doivent pas dépasser {ARG_MAX} -2048 octets."
tripleee

Hm. Bien que les documents gnu soient moins clairs que posix sur cette base et que je n'ai plus accès à la machine qui m'a amené à faire cette déclaration, je ne peux pas confirmer mon interprétation originale sur une implémentation actuelle. Le grep récursif est, bien sûr, toujours préférable s'il est disponible, mais il n'y a pas de raison d'éviter la recette xargs (utilisez -H pour le grep pour éviter que l'invocation finale de grep ne passe qu'un seul nom de fichier, cependant).
m.thome

0

Juste pour le plaisir, une recherche rapide et sale des fichiers * .txt si la réponse @christangrant est trop à taper :-)

grep -r texthere .|grep .txt


0

Voici une fonction récursive (testée légèrement avec bash et sh) qui traverse tous les sous-dossiers d'un dossier donné ($ 1) et utilise des greprecherches pour une chaîne donnée ($ 3) dans des fichiers donnés ($ 2):

$ cat script.sh
#!/bin/sh

cd "$1"

loop () {
    for i in *
    do
        if [ -d "$i" ]
        then
            # echo entering "$i"
            cd "$i"
            loop "$1" "$2"
        fi
    done

    if [ -f "$1" ]
    then
        grep -l "$2" "$PWD/$1"
    fi

    cd ..
}

loop "$2" "$3"

L'exécuter et un exemple de sortie:

$ sh script start_folder filename search_string
/home/james/start_folder/dir2/filename

-2
The syntax is:
cd /path/to/dir
grep -r <"serch_word name"> .

7
Cela n'ajoute pas grand-chose aux autres réponses
Mel
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.