Comment afficher récursivement une liste de fichiers qui a une chaîne et qui n'en a pas spécifiquement une autre? Je veux aussi évaluer le texte des fichiers, pas les noms de fichiers.
Conclusion:
Selon les commentaires, j'ai fini par utiliser:
find . -name "*.html" -exec grep -lR 'base\-maps' {} \; | xargs grep -L 'base\-maps\-bot'
Cela renvoyait des fichiers avec "base-maps" et non "base-maps-bot". Je vous remercie!!
Essaye ça:
grep -rl <string-to-match> | xargs grep -L <string-not-to-match>
Explication: grep -lr
fait récursivement (r) sortir une liste (l) de tous les fichiers qui contiennent <string-to-match>
. xargs boucle sur ces fichiers, appelant grep -L
sur chacun d'eux. grep -L
affichera le nom du fichier uniquement lorsque le fichier ne contient pas <string-not-to-match>
.
L'utilisation de xargs dans les réponses ci-dessus n'est pas nécessaire; vous pouvez réaliser la même chose comme ceci:
find . -type f -exec grep -q <string-to-match> {} \; -not -exec grep -q <string-not-to-match> {} \; -print
grep -q
signifie exécuter silencieusement mais retourner un code de sortie indiquant si une correspondance a été trouvée; find
peut ensuite utiliser ce code de sortie pour déterminer s'il faut continuer à exécuter le reste de ses options. Si -exec grep -q <string-to-match> {} \;
renvoie 0, puis il exécutera -not -exec grep -q <string-not-to-match>{} \;
. Si cela renvoie également 0, il continuera d'exécuter -print
, qui imprime le nom du fichier.
Comme une autre réponse l'a noté, l'utilisation de find
de cette manière présente des avantages majeurs par rapport à grep -Rl
où vous souhaitez uniquement rechercher des fichiers d'un certain type. Si, en revanche, vous voulez vraiment rechercher tous les fichiers, grep -Rl
est probablement plus rapide, car il utilise un processus grep
pour effectuer le premier filtre pour tous les fichiers, au lieu d'un processus grep
distinct pour chaque fichier.
Ces réponses semblent être la correspondance LES DEUX chaînes. La commande suivante devrait mieux fonctionner:
grep -l <string-to-match> * | xargs grep -c <string-not-to-match> | grep '\:0'
Voici une construction plus générique:
find . -name <nameFilter> -print0 | xargs -0 grep -Z -l <patternYes> | xargs -0 grep -L <patternNo>
Cette commande génère des fichiers dont le nom correspond à <nameFilter>
(ajustez les prédicats find
selon vos besoins) qui contiennent <patternYes>
, mais ne contiennent pas <patternNo>
.
Les améliorations sont les suivantes:
Si vous n'avez pas besoin de filtrer par nom (on veut souvent considérer tous les fichiers du répertoire courant), vous pouvez supprimer find
et ajouter -R
au premier grep
:
grep -R -Z -l <patternYes> | xargs -0 grep -L <patternNo>
trouver . -maxdepth 1 -name "* .py" -exec grep -L "string-to-not-to-match" {} \;
Cette commande obtiendra tous les fichiers ".py" qui ne contiennent pas "string-not-to-match" dans le même répertoire.