web-dev-qa-db-fra.com

Utilisez Grep pour trouver tous les fichiers dans un répertoire avec deux chaînes

J'essaie de comprendre la syntaxe correcte pour trouver deux chaînes, la totalité de chaque chaîne, n'importe où (ne doit pas être proche de l'autre) dans un fichier. Donc tout fichier qui a à la fois foo et dire le numéro 321, ne doit pas être seul et peut être une sous-chaîne devrait correspondre. J'ai essayé ce qui suit sans beaucoup de chance:

grep 'foo\|321' *

grep 'foo|321'
24
imaginative

Gnu grep

Devrait être un peu plus rapide parce que la deuxième grep peut fonctionner sur une liste de fichiers.

grep -lZ 'foo' * | xargs -0 grep -l '321'

Posix Grep avec Trouver

find est plus utile si vous souhaitez rechercher des répertoires récursifs (dans ce cas, perdez le -mindepth et -maxdepth options.

find . -mindepth 1 -maxdepth 1 -type f -exec grep -q 'foo' {} \; -exec grep -l '321' {} +
21
kojiro

Vous pouvez le faire avec un script court:

for FILE in *
do
  grep -q foo $FILE && grep -q 321 $FILE && echo $FILE
done

Vous pouvez également le faire sur une ligne:

for FILE in *; do grep -q foo $FILE && grep -q 321 $FILE && echo $FILE; done

grep retourne 0 (vrai) s'il a trouvé la chaîne et le && Séparer les commandes signifie que le second fonctionnera que si le premier était vrai. Les -q Option garantit que grep ne produit rien.

L'écho ne fonctionnera que si les deux chaînes ont été trouvées dans le même fichier.


J'ai pensé à une autre façon de le faire. De cette façon sera probablement plus efficace si les fichiers en question sont supérieurs à ceux installés RAM car il n'a que grep via chaque fichier une fois.

 for FILE in *
 do
   test $(egrep -o "foo|321" $FILE | uniq | sort | uniq | wc -l) -eq 2 && echo $FILE
 done

et la version one-line:

 for FILE in *; do test $(egrep -o "foo|321" $FILE | uniq | sort | uniq | wc -l) -eq 2 && echo $FILE; done
15
Ladadadada

Étrange. Pour moi, les deux variantes travaillent (Grep (GNU Grep) 2.13):

grep 'foo\|321'
grep -E 'foo|321'

éditer 1 - Afficher les fichiers avec les deux matchs uniquement

Les for file in * Réponse fonctionne mais peut devenir un cauchemar de performance (pour de grandes quantités de fichiers): au moins deux processus par fichier. Ceci est plus rapide (dans le GNU World):

find . -type f -print0 | xargs -0 -r grep --files-with-matches --null -- string1 |
  xargs -0 -r grep --files-with-matches -- string2

string1 devrait être celui qui entraîne moins de correspondances.

2
Hauke Laging

Fondamentalement, pour trouver tous les fichiers, y compris une chaîne particulière dans un répertoire, vous pouvez utiliser:

grep -lir "pattern" /path/to/the/dir
  • -l: pour que cette numérisation s'arrête sur le premier match
  • -i: ignorer les distinctions de cas dans le motif et les fichiers d'entrée
  • -r: Rechercher tous les fichiers sous répertoire, récursivement

Pour rechercher deux modèles, essayez ceci:

grep -lr "321" $(grep -lr "foo" /path/to/the/dir)
2
quanta