Comment puis-je trouver les fichiers du répertoire actuel contenant non contiennent le mot foo
(en utilisant grep
)?
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
Si votre grep a l'option -L
(ou --files-without-match
):
$ grep -L "foo" *
Jetez un oeil à ack
. Il effectue automatiquement l’exclusion .svn
pour vous, vous donne les expressions rationnelles Perl et constitue un simple téléchargement d’un programme Perl unique.
L'équivalent de ce que vous cherchez devrait être, dans ack
:
ack -L foo
La commande suivante exclut la nécessité pour la recherche de filtrer les dossiers svn
en utilisant un second grep
.
grep -rL "foo" ./* | grep -v "\.svn"
Vous aurez réellement besoin de:
find . -not -ipath '.*svn*' -exec grep -H -E -o -c "foo" {} \; | grep :0\$
J'ai eu de la chance avec
grep -H -E -o -c "foo" */*/*.ext | grep ext:0
Mes tentatives avec grep -v
viennent de me donner toutes les lignes sans "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
(minuscule), vous obtiendrez le contraire (fichiers avec correspondances)
-l, --files-with-matches
Only the names of files containing selected lines are written
Problème
J'ai besoin de refactoriser un grand projet qui utilise .phtml
fichiers pour écrire du HTML à l'aide du code PHP en ligne. Je veux utiliser les modèles Moustache . Je veux trouver tous les giles .phtml
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 pipes:
Trouver
find .
Recherche récursive de fichiers en commençant par ce répertoire
-iname '*.phtml'
Le nom du fichier doit contenir .phtml
(le i
le rend insensible à la casse)
-exec 'grep -H -E -o -c 'new Mustache' {}'
Exécutez la commande grep
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 en tant qu'expression régulière étendue (c'est-à-dire forcer grep à se comporter comme un egrep).
-o
N'imprime que 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 le nombre de fois où la chaîne new Mustache
apparaît 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 n'inclure que 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 second tube sed 's/..$//'
supprime les deux derniers caractères de chaque ligne, ne laissant que les chemins d'accès aux fichiers.
$> 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
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 sous find si vous devez également filtrer sur l'heure modifiée.
Mon grep n'a pas d'option -L. Je trouve une solution de contournement pour y parvenir.
Les idées sont:
faites la différence entre le fichier 2 dump 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 ">"
Comme l'a commenté @tukan, il existe un rapport de bogue ouvert pour Ag concernant le drapeau -L
/--files-without-matches
:
Comme le rapport de bogue progresse peu, l'option -L
mentionnée ci-dessous ne doit pas être invoquée , tant que le bogue n'a pas été résolu. Utilisez plutôt différentes approches présentées dans ce fil. Citant un commentaire pour le rapport de bogue [mon soulignement]:
Des mises à jour à ce sujet?
-L
ignore complètement les correspondances sur la première ligne du fichier. On dirait que si cela ne va pas être corrigé prochainement , le drapeau doit être entièrement supprimé, car il ne fonctionne pas comme prévu du tout .
Comme alternative puissante à grep
, vous pouvez utiliser le The Silver Searcher - Ag :
Un outil de recherche de code similaire à ack, qui met l’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 récursivement rechercher les fichiers qui ne correspondent pas à foo
, dans le répertoire actuel:
ag -L foo
Pour rechercher uniquement le répertoire actuel des fichiers ne correspondant pas à foo
, spécifiez simplement --depth=0
pour la récursivité:
ag -L foo --depth 0