Comment trouver les fichiers du répertoire courant qui ne contiennent pas le mot foo
(en utilisant grep
)?
Comment trouver les fichiers du répertoire courant qui ne contiennent pas le mot foo
(en utilisant grep
)?
Réponses:
Si votre grep a l' option -L
(ou --files-without-match
):
$ grep -L "foo" *
GREP_OPTIONS='--exclude-dir=.svn --exclude-dir=.git'
: ^)
-rL
au lieu de -L
pour faire correspondre les sous
grep -L 'foo' -- *
La norme est que les commandes qui prennent des options longues utilisent --
pour indiquer qu'il n'y a plus d'options après ce point.
Jetez un oeil à ack
. Il effectue .svn
automatiquement l' exclusion pour vous, vous donne des expressions régulières Perl et est un simple téléchargement d'un seul programme Perl.
L'équivalent de ce que vous recherchez devrait être ack
:
ack -L foo
Vous pouvez le faire avec grep seul (sans trouver).
grep -riL "foo" .
Ceci est l'explication des paramètres utilisés sur grep
-L, --files-without-match
each file processed.
-R, -r, --recursive
Recursively search subdirectories listed.
-i, --ignore-case
Perform case insensitive matching.
Si vous utilisez l
(en minuscules) vous obtiendrez le contraire (fichiers avec correspondances)
-l, --files-with-matches
Only the names of files containing selected lines are written
La commande suivante me donne tous les fichiers qui ne contiennent pas le motif foo
:
find . -not -ipath '.*svn*' -exec grep -H -E -o -c "foo" {} \; | grep 0
grep '0$'
correspondrait aussi à des fichiers avec des multiples de 10 lignes! Vous devez grep ':0$'
à la fin vérifier un ': 0' explicite à la fin de la ligne. Ensuite, vous n'obtiendrez que des fichiers avec zéro ligne correspondante.
La commande suivante exclut la nécessité pour la recherche de filtrer les svn
dossiers à l'aide d'une seconde grep
.
grep -rL "foo" ./* | grep -v "\.svn"
Vous aurez en fait besoin de:
find . -not -ipath '.*svn*' -exec grep -H -E -o -c "foo" {} \; | grep :0\$
Problème
J'ai besoin de refactoriser un grand projet qui utilise des .phtml
fichiers pour écrire du HTML en utilisant du code PHP en ligne. Je souhaite utiliser à la place des modèles Moustache . Je veux trouver tous les .phtml
giles qui ne contiennent pas la chaîne new Mustache
car ils doivent encore être réécrits.
Solution
find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'
Explication
Avant les tuyaux:
Trouver
find .
Rechercher des fichiers récursivement, en commençant dans ce répertoire
-iname '*.phtml'
Le nom de fichier doit contenir .phtml
(le i
rend insensible à la casse)
-exec 'grep -H -E -o -c 'new Mustache' {}'
Exécutez la grep
commande sur chacun des chemins correspondants
Grep
-H
Imprimez toujours les en-têtes de nom de fichier avec les lignes de sortie.
-E
Interpréter le motif comme une expression régulière étendue (c'est-à-dire forcer grep à se comporter comme egrep).
-o
Imprime uniquement la partie correspondante des lignes.
-c
Seul un nombre de lignes sélectionnées est écrit sur la sortie standard.
Cela me donnera une liste de tous les chemins de fichiers se terminant par .phtml
, avec un nombre de fois où la chaîne new Mustache
se produit dans chacun d'eux.
$> find . -iname '*.phtml$' -exec 'grep -H -E -o -c 'new Mustache' {}'\;
./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/orders.phtml:1
./app/MyApp/Customer/View/Account/banking.phtml:1
./app/MyApp/Customer/View/Account/applycomplete.phtml:1
./app/MyApp/Customer/View/Account/catalogue.phtml:1
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0
Le premier canal grep :0$
filtre cette liste pour inclure uniquement les lignes se terminant par :0
:
$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$
./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0
Le deuxième canal sed 's/..$//'
supprime les deux derniers caractères de chaque ligne, ne laissant que les chemins de fichier.
$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'
./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml
./app/MyApp/Customer/View/Account/studio.phtml
./app/MyApp/Customer/View/Account/classadd.phtml
./app/MyApp/Customer/View/Account/orders-trade.phtml
Si vous utilisez git, cela recherche tous les fichiers suivis:
git grep -L "foo"
et vous pouvez effectuer une recherche dans un sous-ensemble de fichiers suivis si vous avez activé ** globbing de sous-répertoire ( shopt -s globstar
dans .bashrc, voir ceci ):
git grep -L "foo" -- **/*.cpp
Mon grep n'a pas d'option -L. Je trouve une solution pour y parvenir.
Les idées sont:
faire la différence entre le 2 fichier de vidage avec la commande diff.
grep 'foo' *.log | cut -c1-14 | uniq > txt1.txt
grep * *.log | cut -c1-14 | uniq > txt2.txt
diff txt1.txt txt2.txt | grep ">"
diff
entre deux flux de sortie (je pense que vous entourez les commandes de parenthèses, et il y a aussi un angle entre les deux), si vos systèmes le prennent en charge, ce que je suppose est la question, car il ne prend pas en chargegrep -L
find *20161109* -mtime -2|grep -vwE "(TRIGGER)"
Vous pouvez spécifier le filtre sous "trouver" et la chaîne d'exclusion sous "grep -vwE". Utilisez mtime under find si vous devez également filtrer l'heure modifiée.
Comme l'a commenté @tukan, il existe un rapport de bogue ouvert pour Ag concernant le drapeau -L
/ --files-without-matches
:
Comme il y a peu de progrès dans le rapport de bogue, l' -L
option mentionnée ci-dessous ne doit pas être invoquée , pas tant que le bogue n'a pas été résolu. Utilisez plutôt les différentes approches présentées dans ce fil. Citant un commentaire pour le rapport de bogue [c'est moi qui souligne]:
Des mises à jour à ce sujet?
-L
ignore complètement les correspondances sur la première ligne du fichier. Il semble que si cela ne va pas être corrigé bientôt, le drapeau devrait être supprimé complètement, car il ne fonctionne pas du tout comme annoncé .
Comme alternative puissante à grep
, vous pouvez utiliser The Silver Searcher - Ag :
Un outil de recherche de code similaire à ack, avec un accent sur la vitesse.
En regardant man ag
, nous trouvons l' option -L
ou --files-without-matches
:
... OPTIONS ... -L --files-without-matches Only print the names of files that don´t contain matches.
C'est-à-dire, pour rechercher récursivement des fichiers qui ne correspondent pas foo
, à partir du répertoire courant:
ag -L foo
Pour rechercher uniquement dans le répertoire actuel les fichiers qui ne correspondent pas foo
, spécifiez simplement --depth=0
la récursivité:
ag -L foo --depth 0
-L
bogue - github.com/ggreer/the_silver_searcher/issues/238
grep -irnw "filepath" -ve "pattern"
ou
grep -ve "pattern" < file
la commande ci-dessus nous donnera le résultat car -v trouve l'inverse du motif recherché
-l
option d'imprimer uniquement le nom du fichier; mais cela affiche toujours les noms de tout fichier contenant une ligne qui ne contient pas le motif. Je crois que l'OP veut trouver les fichiers qui ne contiennent aucune ligne contenant le motif.
La commande suivante peut vous aider à filtrer les lignes qui incluent la sous-chaîne "foo".
cat file | grep -v "foo"
cat
.