Comment trouver tous les fichiers contenant du texte spécifique sous Linux?

5259

J'essaie de trouver un moyen d'analyser l'ensemble de mon système Linux pour tous les fichiers contenant une chaîne de texte spécifique. Juste pour clarifier, je cherche du texte dans le fichier, pas dans le nom du fichier.

Quand je cherchais comment faire cela, je suis tombé sur cette solution deux fois:

find / -type f -exec grep -H 'text-to-find-here' {} \;

Mais ça ne marche pas. Il semble afficher tous les fichiers du système.

Est-ce proche de la bonne façon de procéder? Sinon, comment dois-je? Cette capacité à trouver des chaînes de texte dans des fichiers serait extrêmement utile pour certains projets de programmation que je fais.

Nathan
la source
21
rappelez-vous que grep interprétera tout .comme un caractère générique à un seul caractère, entre autres. Mon conseil est de toujours utiliser fgrep ou egrep.
Walter Tross
10
de toute façon, vous y étiez presque! Remplacez simplement -Hpar -l(et peut-être greppar fgrep). Pour exclure des fichiers avec certains modèles de noms, vous utiliseriez findd'une manière plus avancée. Il vaut la peine d'apprendre à utiliser find, cependant. Justement man find.
Walter Tross
6
find … -exec <cmd> +est plus facile à taper et plus rapide que find … -exec <cmd> \;. Il ne fonctionne que s'il <cmd>accepte un nombre quelconque d'arguments de nom de fichier. Le gain de temps d'exécution est particulièrement important s'il <cmd>est lent à démarrer comme les scripts Python ou Ruby.
hagello
Pour rechercher de façon non récursive dans un chemin donné, la commande est `grep --include = *. Txt -snw" pattern "thepath / *.
Stéphane Laurent
@ StéphaneLaurent Je pense que tu compliques trop. Dites simplementgrep "pattern" path/*.txt
fedorqui 'SO arrêtez de nuire'

Réponses:

9523

Procédez comme suit:

grep -rnw '/path/to/somewhere/' -e 'pattern'
  • -rou -Rest récursif,
  • -n est le numéro de ligne, et
  • -w signifie correspondre au mot entier.
  • -l (L minuscule) peut être ajouté pour donner simplement le nom de fichier des fichiers correspondants.

Avec ces derniers , --exclude, --include, --exclude-dirdrapeaux pourraient être utilisés pour la recherche efficace:

  • Cela ne recherchera que les fichiers ayant des extensions .c ou .h:

    grep --include=\*.{c,h} -rnw '/path/to/somewhere/' -e "pattern"
    
  • Cela exclura la recherche de tous les fichiers se terminant par l'extension .o:

    grep --exclude=*.o -rnw '/path/to/somewhere/' -e "pattern"
    
  • Pour les répertoires, il est possible d'exclure un ou des répertoires particuliers via le --exclude-dirparamètre. Par exemple, cela exclura les répertoires dir1 /, dir2 / et tous correspondant à * .dst /:

    grep --exclude-dir={dir1,dir2,*.dst} -rnw '/path/to/somewhere/' -e "pattern"
    

Cela fonctionne très bien pour moi, pour atteindre presque le même objectif que le vôtre.

Pour plus d'options, vérifiez man grep.

rakib_
la source
74
utilisez --exclude. comme "grep -rnw --exclude = *. o 'directory' -e" pattern "
rakib_
98
cela vaut la peine d'être noté: il semble que l' roption soit paresseuse (traverse d'abord en profondeur, puis s'arrête après le premier répertoire), tandis qu'elle Rest gourmande (traversera correctement tout l'arbre).
Eliran Malka
5
grep -rnw "String que je cherchais" a fait ce dont j'avais besoin. Merci!
ViliusK
33
Remarque (en particulier pour les débutants): les guillemets dans la commande ci-dessus sont importants.
madD7
69
@Eliran Malka Rfr parcourra rles deux répertoires correctement, mais Rsuivra des liens symboliques.
bzeaman
1499

Vous pouvez utiliser grep -ilR:

grep -Ril "text-to-find-here" /
  • i signifie ignorer la casse (facultatif dans votre cas).
  • R signifie récursif.
  • l signifie "afficher le nom du fichier, pas le résultat lui-même".
  • / signifie commencer à la racine de votre machine.
fedorqui 'SO arrête de nuire'
la source
85
D'après mon expérience, le -iralentit beaucoup, alors ne l'utilisez pas si ce n'est pas nécessaire. Testez-le dans un certain répertoire puis généralisez. Il devrait être terminé en quelques minutes. Je pense qu'une expression régulière le ralentirait. Mais mes commentaires sont basés sur des suppositions, je vous propose de le tester avec timeen face de la ligne.
fedorqui 'SO arrête de nuire'
4
Oui, /*c'est pour ça. Quoi qu'il en soit, je viens de le tester et j'ai remarqué que cela /fonctionne.
fedorqui 'SO arrête de nuire'
10
Si vous ne recherchez pas à l'aide d'une expression régulière, vous pouvez utiliser fgrep à la place de grep sur la plupart des systèmes.
markle976
8
Oui @ markle976, en fait de l' homme grep: fgrep is the same as grep -F -> Interpret PATTERN as a list of fixed strings.
fedorqui 'SO arrête de nuire'
17
Vous pouvez remplacer / par le chemin du répertoire grep -Ril "text-to-find-here" ~/sites/ou utiliser. pour le répertoire actuelgrep -Ril "text-to-find-here" .
Black
329

Vous pouvez utiliser ack . C'est comme grep pour le code source. Vous pouvez scanner l'ensemble de votre système de fichiers avec.

Faites juste:

ack 'text-to-find-here'

Dans votre répertoire racine.

Vous pouvez également utiliser des expressions régulières , spécifier le type de fichier, etc.


MISE À JOUR

Je viens de découvrir The Silver Searcher , qui est comme ack mais 3 à 5 fois plus rapide et ignore même les modèles d'un .gitignorefichier.

Stephan
la source
57
Très utile, simple et rapide. Avertissement: "Sur les distributions dérivées de Debian, ack est empaqueté comme" ack-grep "parce que" ack "existait déjà" (de Beyondgrep.com/install ). Vous pouvez finir par exécuter un convertisseur de code Kanji sur ces Linux ...
Jose_GD
11
ack ou ack-grep a de jolis points forts, mais trouver + grep quand il est utilisé correctement est bien meilleur en
termes de
14
Notez que ripgrep est plus rapide que tout ce qui est mentionné ici, y compris The Silver Searcher et plain 'ol grep. Voir cet article de blog pour la preuve.
Radon Rosborough
194

Vous pouvez utiliser:

grep -r "string to be searched"  /path/to/dir

Le rsignifie récursif et va donc rechercher dans le chemin spécifié et aussi dans ses sous-répertoires. Cela vous indiquera le nom du fichier et imprimera la ligne dans le fichier où la chaîne apparaît.

Ou une commande similaire à celle que vous essayez (exemple:) pour rechercher dans tous les fichiers javascript (* .js):

find . -name '*.js' -exec grep -i 'string to search for' {} \; -print

Cela imprimera les lignes dans les fichiers où le texte apparaît, mais cela n'imprimera pas le nom du fichier.

En plus de cette commande, nous pouvons également écrire ceci: grep -rn "Chaîne à rechercher" / chemin / vers / répertoire / ou / fichier -r: recherche récursive n: le numéro de ligne sera affiché pour les correspondances

Learner_19
la source
1
Merci pour la version find. Ma version grep (busybox pour NAS) n'a pas l'option -r, j'avais vraiment besoin d'une autre solution!
jc
3
Merci pour la version 'find'! Il est si important de pouvoir filtrer par ' .js' ou ' .txt', etc. Personne ne veut passer des heures à attendre que grep finisse de rechercher toutes les vidéos multi-gigaoctets des dernières vacances en famille, même si la commande est plus facile à taper.
mightypile
meilleure grep que la version acceptée, car acceptée ne recherche pas les demi-mots
waza123
114

Vous pouvez utiliser ceci:

grep -inr "Text" folder/to/be/searched/
AR
la source
12
le plus simple, verbeux, récursif et insensible à la casse. pouces vers le haut.
Francesco Casula
si vous ajoutez -A3 est encore meilleur
albanx
73

Liste des noms de fichiers contenant un texte donné

Tout d'abord, je crois que vous avez utilisé -Hau lieu de -l. Vous pouvez également essayer d'ajouter le texte entre guillemets suivi de {} \.

find / -type f -exec grep -l "text-to-find-here" {} \; 

Exemple

Supposons que vous recherchez des fichiers contenant du texte spécifique "Licence Apache" dans votre répertoire. Il affichera des résultats quelque peu similaires à ceux ci-dessous (la sortie sera différente en fonction du contenu de votre répertoire).

bash-4.1$ find . -type f -exec grep -l "Apache License" {} \; 
./net/java/jvnet-parent/5/jvnet-parent-5.pom
./commons-cli/commons-cli/1.3.1/commons-cli-1.3.1.pom
./io/swagger/swagger-project/1.5.10/swagger-project-1.5.10.pom
./io/netty/netty-transport/4.1.7.Final/netty-transport-4.1.7.Final.pom
./commons-codec/commons-codec/1.9/commons-codec-1.9.pom
./commons-io/commons-io/2.4/commons-io-2.4.pom
bash-4.1$ 

Supprimer la sensibilité à la casse

Même si vous n'êtes pas habitué au cas comme "texte" vs "TEXTE", vous pouvez utiliser le -icommutateur pour ignorer la casse. Vous pouvez lire plus de détails ici .

J'espère que cela vous aidera.

lkamal
la source
2
C'est ce que fait cette commande: findpassera tous les chemins qu'elle trouve à la commande grep -l "text-to-find-here" <file found>". Vous pouvez ajouter des restrictions au nom de fichier, par exemple find / -iname "*.txt"pour rechercher uniquement dans les fichiers dont le nom se termine par.txt
Mene
1
@Auxiliary - inclus un exemple de sortie pour éviter toute confusion pour les lecteurs.
lkamal
2
@Mene C'est un état vraiment triste que le commentaire des Auxiliaires ait plus de votes que le vôtre ... même si leur commentaire date de 2014 et le vôtre est de 2017 que leur commentaire a 6 alors qu'il devrait avoir exactement 0 et que le vôtre n'en avait qu'un (maintenant deux) n'est pas pas quelque chose que j'aimerais croire.
Pryftan
@Mene Cela étant dit, la -inamecasse est insensible, ce qui signifie qu'il trouverait également des fichiers .TXT, par exemple, ainsi que TxT et TXt et ainsi de suite.
Pryftan,
66

grep( GNU ou BSD )

Vous pouvez utiliser l' grepoutil pour rechercher récursivement le dossier actuel, comme:

grep -r "class foo" .

Remarque: -r- Recherche récursivement dans les sous-répertoires.

Vous pouvez également utiliser la syntaxe de globalisation pour rechercher dans des fichiers spécifiques tels que:

grep "class foo" **/*.c

Remarque: En utilisant l' option globbing ( **), il analyse tous les fichiers de manière récursive avec une extension ou un motif spécifique. Pour activer cette syntaxe, exécutez: shopt -s globstar. Vous pouvez également utiliser **/*.*pour tous les fichiers (sauf caché et sans extension) ou tout autre modèle.

Si vous avez l'erreur que votre argument est trop long, envisagez de restreindre votre recherche ou utilisez findplutôt une syntaxe telle que:

find . -name "*.php" -execdir grep -nH --color=auto foo {} ';'

Vous pouvez également utiliser ripgrep.

ripgrep

Si vous travaillez sur des projets plus importants ou de gros fichiers, vous devez utiliser à la ripgrepplace, comme:

rg "class foo" .

Découvrez les documents, les étapes d'installation ou le code source sur la page du projet GitHub .

Il est beaucoup plus rapide que tout autre outil comme GNU / BSD grep , ucg, ag, sift, ack, ptou similaire, puisqu'il est construit sur le dessus du moteur regex de Rust qui utilise des automates finis, SIMD et optimisations littérales agressives pour faire une recherche très rapide.

Il prend en charge les modèles ignorés spécifiés dans les .gitignorefichiers, de sorte qu'un seul chemin de fichier peut être comparé à plusieurs modèles glob simultanément.


Vous pouvez utiliser les paramètres communs tels que:

  • -i - Recherche insensible.
  • -I - Ignorez les fichiers binaires.
  • -w - Rechercher les mots entiers (contrairement à la correspondance partielle des mots).
  • -n - Montrez la ligne de votre match.
  • -C/ --context(par exemple -C5) - Augmente le contexte, de sorte que vous voyez le code environnant.
  • --color=auto - Marquez le texte correspondant.
  • -H - Affiche le nom du fichier où se trouve le texte.
  • -c- Affiche le nombre de lignes correspondantes. Peut être combiné avec -H.
kenorb
la source
1
Je trouve également que le globbing étendu est utile. Mais gardez à l'esprit que s'il y a vraiment un très grand nombre de fichiers, vous pouvez obtenir une erreur "Argument list too long". (Un simple globbing est également sujet à ce type d'erreur).
Yoory N.
2
Pour inhaler un système de fichiers entier, rg va être beaucoup moins douloureux que presque tout autre outil.
lk
55

Si votre grepne prend pas en charge la recherche récursive, vous pouvez combiner findavec xargs:

find / -type f | xargs grep 'text-to-find-here'

Je trouve cela plus facile à retenir que le format pour find -exec.

Cela affichera le nom de fichier et le contenu de la ligne correspondante, par exemple

/home/rob/file:text-to-find-here

Drapeaux facultatifs que vous voudrez peut-être ajouter à grep:

  • -i - recherche insensible à la casse
  • -l - afficher uniquement le nom de fichier où la correspondance a été trouvée
  • -h - affiche uniquement la ligne qui correspond (pas le nom du fichier)
RobEarl
la source
3
Cela équivaut à grep 'text-to-find-here'sans nom de fichier s'il findne trouve rien. Cela va se bloquer et attendre la saisie de l'utilisateur! Ajouter --no-run-if-emptyen option à xargs.
hagello
3
Cette combinaison de find et xargs ne fonctionne pas comme prévu si les noms de fichiers ou de répertoires contiennent des espaces (caractères que xargs interprète comme séparateurs). Utilisez find … -exec grep … +. Si vous insistez pour utiliser find avec xargs, utilisez -print0et -0.
hagello
43
grep -insr "pattern" *
  • i: Ignorez les distinctions de casse dans le MOTIF et les fichiers d'entrée.
  • n: Préfixez chaque ligne de sortie avec le numéro de ligne basé sur 1 dans son fichier d'entrée.
  • s: Supprime les messages d'erreur concernant les fichiers inexistants ou illisibles.
  • r: Lire tous les fichiers sous chaque répertoire, récursivement.
enfinet
la source
3
Pouvez-vous expliquer comment votre réponse améliore les autres réponses, ou comment elle est suffisamment différente d'eux?
Amos M. Carpenter
pas très complexe à retenir, couvrira tous les modèles (casse-sensibilité -> désactivé, inclut les noms de fichier et le numéro de ligne et fera une recherche récursive, etc.) et l'utilisation de "*" à la fin recherchera tous les répertoires (pas besoin de spécifier chemin ou nom de répertoire).
enfinet
Désolé, j'aurais dû être plus clair: ce serait formidable si vous pouviez inclure cette explication dans votre réponse. Dans l'état actuel des choses, en particulier avec tant d'autres réponses similaires déjà, il est difficile de voir à partir d'une réponse aussi courte quel serait l'avantage de l'essayer par rapport à la réponse acceptée ou à l'une des réponses votées.
Amos M. Carpenter
6
@ AmosM.Carpenter Une chose que j'aime dans cette réponse est de souligner l'argument de suppression, qui peut aider à filtrer le bruit qui n'a pas d'importance pour obtenir les résultats que nous voulons réellement. Grep imprime des erreurs comme, "Fonction non implémentée", "Argument invalide", "Ressource indisponible", etc. etc. sur certains "fichiers".
leetNightshade
@leetNightshade: Je suppose que vous m'adressez votre commentaire parce que j'ai demandé une explication sur le post original clairsemé. Veuillez voir la grande révision de Fabio pour que mes commentaires précédents aient un sens.
Amos M. Carpenter
39

Il y a un nouvel utilitaire appelé The Silversearcher

sudo apt install silversearcher-ag

Il fonctionne en étroite collaboration avec Git et d'autres VCS. Vous n'aurez donc rien dans un .git ou un autre répertoire.

Vous pouvez simplement utiliser

ag "Search query"

Et il fera le travail pour vous!

Neil Agarwal
la source
35

Comment trouver tous les fichiers contenant du texte spécifique sous Linux? (...)

Je suis tombé sur cette solution deux fois:

find / -type f -exec grep -H 'text-to-find-here' {} \;


Si vous utilisez find like dans votre exemple, il vaut mieux ajouter -s( --no-messages) à grepet 2>/dev/nullà la fin de la commande pour éviter de nombreux messages d' autorisation refusée émis par grepet find:

find / -type f -exec grep -sH 'text-to-find-here' {} \; 2>/dev/null

find est l'outil standard pour rechercher des fichiers - combiné avec grep lors de la recherche de texte spécifique - sur des plateformes de type Unix. Lacommande find est souvent combinée avec xargs , soit dit en passant.

Des outils plus rapides et plus faciles existent dans le même but - voir ci-dessous. Mieux vaut les essayer, à condition qu'ils soient disponibles sur votre plateforme , bien sûr:

Des alternatives plus rapides et plus faciles

RipGrep - l'outil de recherche le plus rapide:

rg 'text-to-find-here' / -l

The Silver Searcher :

ag 'text-to-find-here' / -l

ack :

ack 'text-to-find-here' / -l

Remarque: Vous pouvez également ajouter 2>/dev/nullà ces commandes pour masquer de nombreux messages d'erreur.


Attention : à moins que vous ne puissiez vraiment pas l'éviter, ne cherchez pas dans '/' (le répertoire racine) pour éviter une recherche longue et inefficace! Donc, dans les exemples ci-dessus, vous feriez mieux de remplacer ' / ' par un nom de sous-répertoire, par exemple "/ home" selon l'endroit où vous voulez réellement rechercher ...

Bludzee
la source
'find est l'outil standard pour rechercher des fichiers contenant du texte spécifique sur des plateformes de type Unix' me semble plutôt ambigu. Même récursif grep findne recherche pas directement le texte à l'intérieur des fichiers. Et peut-être que ces outils supplémentaires sont utiles pour certains, mais les anciens temporisateurs et ceux qui sont bien habitués, par exemple grep, ne leur donneraient pas du tout de temps (enfin je ne le ferai certainement pas). Mais je ne dis pas qu'ils sont inutiles.
Pryftan
".... contenant un texte spécifique ...": cette partie de la phrase n'était pas exacte (car ce n'est pas elle-même qui traite de cette partie de la recherche). Édité. Merci.
Bludzee
Heureux d'avoir pu aider! La seule chose d'autre en un coup d'œil très très rapide est de changer le dossier de mots en répertoire, mais je sais que c'est une croisade que je ne gagnerai jamais complètement. Ne pas abandonner si ...
Pryftan
Pourquoi pas "répertoire" au lieu de "dossier", mais pourquoi? Partagez votre "croisade"!
Bludzee
Je dis plutôt utiliser le répertoire! En référence à: vous feriez mieux de remplacer '/' par un nom de sous-dossier Et c'est une bête noire à moi .. d'autant plus que même Windows l'appelait 'répertoire'. Ah ... peut-être que vous avez compris. Pourquoi? Eh bien parce que c'est comme ça qu'on l'appelle. Cela s'appelle également cela au niveau du système de fichiers. Et regardez-le de cette façon: at-il déjà été appelé (pour DOS) fol? Non bien sûr que non; il a été appelé dir(et je crois qu'il l'est toujours). Le dossier est une chose conçue pour (je suppose) la convivialité, bien que dans ce cas, il soit peut-être stupide pour les utilisateurs moins «avancés»?
Pryftan
29

Essayer:

find . -name "*.txt" | xargs grep -i "text_pattern"
venkat
la source
5
Ceci est en fait un excellent exemple de quand NE PAS utiliser xargscomme ça .. considérez ceci. echo "file bar.txt has bar" > bar.txt; echo "file foo bar.txt has foo bar" > "foo bar.txt"; echo "You should never see this foo" > foo; find . -name "*.txt" | xargs grep -i foo # ./foo:You should never see this foo. L' xargsici correspondait au fichier FAUX et ne correspondait PAS au fichier prévu. Soit utiliser un find .. -print0 | xargs -0 ...mais c'est une utilisation inutile d'un tuyau ou mieuxfind ... -exec grep ... {} +
shalomb
29

Utilisez pwdpour rechercher à partir de n'importe quel répertoire dans lequel vous vous trouvez, en recursant vers le bas

grep -rnw `pwd` -e "pattern"

Mise à jour Selon la version de grep que vous utilisez, vous pouvez omettre pwd. Sur les versions plus récentes, .semble être le cas par défaut pour grep si aucun répertoire n'est donné ainsi:

grep -rnw -e "pattern"

ou

grep -rnw "pattern"

fera la même chose que ci-dessus!

mahatmanich
la source
3
l'utilisation pwdn'est pas nécessaire du tout, car c'est la valeur par défaut. grep -rnw "pattern"suffit.
fedorqui 'SO arrêtez de nuire'
et en fait, grep -rnwet similaire est ce qui a été répondu comme il y a trois ans, je ne vois pas comment cette réponse ajoute de la valeur.
fedorqui 'SO arrête de nuire'
La réponse sélectionnée ne montre pas le modèle par défaut, et 5 personnes semblaient l'avoir trouvé utile
mahatmanich
Que voulez-vous dire par "modèle par défaut"? La réponse acceptée contient grep -rnw '/path/to/somewhere/' -e "pattern"ce que vous avez ici. 5 votes après 2,3 millions de visites ne signifient pas grand-chose.
fedorqui 'SO arrête de faire du mal'
Je suis d'accord :-) ce qui me manquait dans la réponse d'origine est le cas d'utilisation que vous n'avez pas du tout à donner de chemin ou à rechercher récursivement dans le répertoire courant qui ne se reflète pas dans la réponse acceptée. C'était donc une bonne expérience d'apprentissage sur grep pour creuser un peu plus.
mahatmanich
19

grep peut être utilisé même si nous ne recherchons pas de chaîne.

Tout simplement en cours d'exécution,

grep -RIl "" .

imprimera le chemin d'accès à tous les fichiers texte, c'est-à-dire ceux contenant uniquement des caractères imprimables.

Alex Jasmin
la source
2
Je ne vois pas comment c'est mieux que d'utiliser un simple lsou find(pour le récursif)
fedorqui 'SO arrêtez de nuire'
17

Voici la liste de plusieurs commandes qui peuvent être utilisées pour rechercher un fichier.

grep "text string to search” directory-path

grep [option] "text string to search” directory-path

grep -r "text string to search” directory-path

grep -r -H "text string to search” directory-path

egrep -R "word-1|word-2” directory-path

egrep -w -R "word-1|word-2” directory-path
Atul Arvind
la source
5
qu'est-ce que cela ajoute aux réponses existantes?
fedorqui 'SO stop harming'
@fedorqui egrepest équivalent à grep -Eet cela signifie que --extended-regexpvous pouvez trouver des détails ici unix.stackexchange.com/a/17951/196072
omerhakanbilici
15
find /path -type f -exec grep -l "string" {} \;

Explication des commentaires

find est une commande qui vous permet de rechercher des fichiers et d'autres objets tels que des répertoires et des liens dans des sous-répertoires d'un chemin donné. Si vous ne spécifiez pas de masque que les noms de fichiers doivent respecter, il énumère tous les objets de répertoire.

-type f specifies that it should proceed only files, not directories etc.
-exec grep specifies that for every found file, it should run grep command, passing its filename as an argument to it, by replacing {} with the filename
Vinod Joshi
la source
15

Essayer:

find / -type f -exec grep -H 'text-to-find-here' {} \;

qui va rechercher tous les systèmes de fichiers, car / s'agit du dossier racine.

Pour l'utilisation du dossier de départ:

find ~/ -type f -exec grep -H 'text-to-find-here' {} \;

Pour l'utilisation du dossier actuel:

find ./ -type f -exec grep -H 'text-to-find-here' {} \;
user4863663
la source
Peut-être que les détails sur les différences de dossiers sont évidents pour beaucoup ... mais aussi très utiles pour les débutants. +1
nilon
1
qu'est-ce que cela ajoute aux réponses existantes?
fedorqui 'SO stop harming'
Appelez ça ma croisade mais le mot est «répertoire». Ce n'est pas Windows (qui utilisait de toute façon «répertoire» - avant 9x). Veuillez arrêter de dire «dossier». Quant à votre dernière commande, vous n'avez même pas besoin du '/' juste FYI.
Pryftan
15

J'espère que cela vous sera utile ...

Développer grepun peu pour donner plus d'informations dans la sortie, par exemple, pour obtenir le numéro de ligne dans le fichier où se trouve le texte, peut se faire comme suit:

find . -type f -name "*.*" -print0 | xargs --null grep --with-filename --line-number --no-messages --color --ignore-case "searthtext"

Et si vous avez une idée du type de fichier, vous pouvez affiner votre recherche en spécifiant les extensions de type de fichier à rechercher, dans ce cas .pasOU les .dfmfichiers:

find . -type f \( -name "*.pas" -o -name "*.dfm" \) -print0 | xargs --null grep --with-filename --line-number --no-messages --color --ignore-case "searchtext"

Brève explication des options:

  1. .dans le findspécifie du répertoire en cours.
  2. -name" *.*": Pour tous les fichiers (-name " *.pas" -o "-name *.dfm"): Seuls les *.pasOR *.dfmfichiers, ou spécifiés avec-o
  3. -type f spécifie que vous recherchez des fichiers
  4. -print0et --nullde l'autre côté du |(pipe) sont les plus cruciaux, en passant le nom de fichier de findà l' grepincrusté dans le xargs, permettant le passage de noms de fichiers AVEC des espaces dans les noms de fichiers, permettant à grep de traiter le chemin et le nom de fichier comme une chaîne, et ne pas le briser sur chaque espace.
Gert van Biljon
la source
-name '*.*'n'est pas ce que vous dites; il ne reprendrait pas un fichier appelé «fichier» car le motif ne correspond pas à cela (pas de .ext); *serait cependant (bien. fichiers de côté). Mais il y a une autre chose: si vous voulez tous les fichiers, pourquoi prendre la peine de spécifier un nom de fichier en premier lieu? Aucun autre commentaire - sauf qu'il est bon de savoir qu'il y a encore des gens qui n'utilisent pas le «dossier» de la terminologie MS (ce qui, après l'avoir suffisamment dit, je ne l'ajouterais pas, mais je voulais souligner la déclaration légèrement incorrecte que vous avez faite avec les noms de fichiers - ainsi que la redondance / l'inutilité dans le cas de «tous»).
Pryftan
15

Un simple findpeut fonctionner à portée de main. alias dans votre ~/.bashrcfichier:

alias ffind find / -type f | xargs grep

Démarrez un nouveau terminal et lancez:

ffind 'text-to-find-here'
danglingpointer
la source
14

J'ai écrit un script Python qui fait quelque chose de similaire. C'est ainsi qu'il faut utiliser ce script.

./sniff.py path pattern_to_search [file_pattern]

Le premier argument,, pathest le répertoire dans lequel nous allons effectuer une recherche récursive. Le deuxième argument,, pattern_to_searchest une expression régulière que nous voulons rechercher dans un fichier. Nous utilisons le format d'expression régulière défini dans la bibliothèque Python re . Dans ce script, le .correspond également à la nouvelle ligne.

Le troisième argument file_pattern,, est facultatif. Il s'agit d'une autre expression régulière qui fonctionne sur un nom de fichier. Seuls les fichiers correspondant à cette expression régulière seront pris en compte.

Par exemple, si je veux rechercher des fichiers Python avec l'extension pycontenant Pool(suivie d'un mot Adaptor, je fais ce qui suit,

./sniff.py . "Pool(.*?Adaptor"  .*py
./Demos/snippets/cubeMeshSigNeur.py:146 
./Demos/snippets/testSigNeur.py:259 
./python/moose/multiscale/core/mumbl.py:206 
./Demos/snippets/multiComptSigNeur.py:268 

Et le tour est joué, il génère le chemin des fichiers correspondants et le numéro de ligne sur lequel la correspondance a été trouvée. Si plusieurs correspondances ont été trouvées, chaque numéro de ligne sera ajouté au nom de fichier.

Dilawar
la source
14

Si vous souhaitez strictement utiliser, findutilisez find + grep:

find /path/to/somewhere/ -type f -exec grep -nw 'textPattern' {} \;

pas:

1.Utilisez findpour rechercher des fichiers,
2.Ensuite, exécutez-les grepsur tous.

Cela peut vous permettre de findrechercher des fichiers.

  • Utilisez -name Patternsi vous souhaitez grepuniquement certains fichiers:

    find /path/to/somewhere/ -type f -name \*.cpp -exec grep -nw 'textPattern' {} \;

Vous pouvez jouer avec et utiliser différentes options findpour améliorer ou affiner votre recherche de fichiers.

BreakBadSP
la source
Quelle est la différence? Cela fonctionnera-t-il avec des espaces dans le chemin du fichier?
Peter Mortensen
13

Utilisation:

grep -c Your_Pattern *

Cela indiquera le nombre de copies de votre modèle dans chacun des fichiers du répertoire actuel.

Dr_Hope
la source
13

grep est votre bon ami pour y parvenir.

grep -r <text_fo_find> <directory>

Si vous ne vous souciez pas de la casse du texte à rechercher, utilisez:

grep -ir <text_to_find> <directory>
Prash
la source
Dans mon cas, il semble qu'il recherche partout, même si je spécifie le répertoire
Pathros
@Pathros Probablement lié à la récursivité activée et au répertoire que vous spécifiez. Autrement dit, la récursion change les choses de cette façon.
Pryftan
@Pathros Oh et s'il y a des -s dans la chaîne de recherche, vous voudrez d'abord passer --à grep; cela peut provoquer des effets secondaires intéressants sinon!
Pryftan
13

Je suis fasciné par la simplicité de grep avec 'rl':

grep -rl 'pattern_to_find' /path/where/to/find

-r to recursively find a file / directory inside directories..
-l to list files matching the 'pattern'

Utilisez '-r' sans 'l' pour voir les noms de fichiers suivis du texte dans lequel se trouve le motif !

grep -r 'pattern_to_find' /path/where/to/find

Cela fonctionne tout simplement parfait ...

nitinr708
la source
Cela fonctionne également dans Git Bash (Windows).
Peter Mortensen
Mais cela implique que chaque fichier doit être recherché (pas de filtre sur le nom de fichier ou le niveau d'extension de fichier, comme .txt). Ou existe-t-il un moyen de le faire?
Peter Mortensen le
12

Pour rechercher la chaîne et produire uniquement cette ligne avec la chaîne de recherche:

for i in $(find /path/of/target/directory -type f); do grep -i "the string to look for" "$i"; done

par exemple:

for i in $(find /usr/share/applications -type f); \
do grep -i "web browser" "$i"; done

Pour afficher le nom de fichier contenant la chaîne de recherche:

for i in $(find /path/of/target/directory -type f); do if grep -i "the string to look for" "$i" > /dev/null; then echo "$i"; fi; done;

par exemple:

for i in $(find /usr/share/applications -type f); \
do if grep -i "web browser" "$i" > /dev/null; then echo "$i"; \
fi; done;

la source
1
Je ne vois que des inconvénients par rapport à l'utilisation find … -exec grep 'str' {} \;(si vous devez utiliser finddu tout).
phk
1
Cela se briserait horriblement si l'un des fichiers trouvés par les findespaces contenus .. vous pourriez finir par greppingles mauvais fichiers et / ou manquer les bons fichiers. Utilisez simplement find ... -exec grep ...si vous avez besoin d'utiliser find.. mais dans ce cas, un grep -r ...suffit.
shalomb
1
quel est l'intérêt d'utiliser une boucle sur les résultats de find pour ensuite grep? Cela devient inutilement compliqué.
fedorqui 'SO stop harming'
12

Il existe un ackoutil qui ferait exactement ce que vous recherchez.

http://linux.die.net/man/1/ack

ack -i search_string folder_path/*

Vous pouvez ignorer la -irecherche sensible à la casse

Copain
la source
2
Qu'est-ce que cela ajoute aux réponses existantes? Cela a déjà été suggéré il y a plus de trois ans.
fedorqui 'SO arrête de nuire'
1
@fedorqui 1) pas de tuyauterie! 2) Utilisez des expressions régulières. 3) Obtenez les numéros de ligne, le nom du fichier avec le chemin relatif, le texte en surbrillance, etc. Voir la sortie de la commande "ack include \ | hpp" qui recherche les mots-clés "include" ou "hpp" sous mon dossier de recherche et sous-dossiers. J'espère que le point est clair. Voici l'exemple de sortie (impossible d'afficher les mots clés en surbrillance avec un texte simple) process / child.hpp 11: boost / process / child.hpp process / all.hpp 21: #include <boost / process / execute.hpp>
Pal
12

Toutes les réponses précédentes suggèrent grep et find. Mais il existe un autre moyen: utiliser Midnight Commander

C'est un utilitaire gratuit (30 ans, prouvé par le temps) qui est visuel sans être GUI. Il a des tonnes de fonctions et la recherche de fichiers n'est que l'une d'entre elles.

Peter M. - représente Monica
la source
ranger serait dans la même idée
nilon
11

La commande ci-dessous fonctionnera bien pour cette approche:

find ./ -name "file_pattern_name"  -exec grep -r "pattern" {} \;
Pradeep Goswami
la source
2
quel est l'intérêt d'utiliser findpuis grep -r? Ils sont destinés à la même chose, donc c'est redondant.
fedorqui 'SO arrête de nuire'
ohh !! corrigé, trouver est en fait pour exécuter grep sur des fichiers filtrés et pas tous, merci
Pradeep Goswami
2
encore, cela n'a aucun sens, vous pouvez filtrer avec find.
fedorqui `` SO arrêtez de nuire '' du
11

Évitez les tracas et installez ack-grep. Il élimine beaucoup de problèmes d'autorisation et de devis.

apt-get install ack-grep

Ensuite, allez dans le répertoire que vous souhaitez rechercher et exécutez la commande ci-dessous

cd /
ack-grep "find my keyword"
Kareem
la source