web-dev-qa-db-fra.com

Comment trouver des fichiers qui ne contiennent pas un motif de chaîne donné?

Comment puis-je trouver les fichiers du répertoire actuel contenant non contiennent le mot foo (en utilisant grep)?

468
Senthil Kumar

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
16
Senthil Kumar

Si votre grep a l'option -L (ou --files-without-match):

$ grep -L "foo" *
748
ghostdog74

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
44
Andy Lester

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"
13
user999305

Vous aurez réellement besoin de:

find .  -not  -ipath '.*svn*' -exec  grep  -H -E -o -c  "foo"  {} \; | grep :0\$
9
Forrest Tiffany

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".

6
Johnny

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
5
Adrian

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
2
Gruffy

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.

1
zandeep

Mon grep n'a pas d'option -L. Je trouve une solution de contournement pour y parvenir.

Les idées sont:

  1. vider tout le nom de fichier contenant la chaîne méritée dans un fichier txt1.txt.
  2. dump tout le nom de fichier du répertoire dans un fichier txt2.txt.
  3. 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 ">"
    
1
user6305682

Rapport de bogue ouvert

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 .


Silver Searcher - Ag (fonction souhaitée - voir le rapport de bogue)

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
1
dfri