Recherche de tuyau dans grep -v

18

J'essaie de trouver tous les fichiers qui sont d'un certain type et ne contiennent pas une certaine chaîne. J'essaye de m'y prendre en cherchant à grep -v

exemple:

find -type f -name '*.java' | xargs grep -v "something something"

Ça n'a pas l'air de fonctionner. Il semble simplement renvoyer tous les fichiers trouvés par la commande find. Ce que j'essaie de faire est de trouver fondamentalement tous les fichiers .java qui correspondent à un certain nom de fichier (par exemple, se terminent par «Pb» comme dans SessionPb.java) et qui n'ont pas de «étend quelque chose» à l'intérieur.

Je soupçonne que je me trompe. Alors, à quoi devrait ressembler la commande à la place?

Hyangelo
la source
vous pourriez ajouter ce qui vous fait penser que cela n'a pas fonctionné. peut-être que votre expression grep est trop explicite? a besoin d'un «-i» pour l'insensibilité à la casse? Voir aussi ma réponse ci-dessous ...
lornix

Réponses:

21

Il n'y a aucun besoin xargsici. Vous devez également utiliser grepavec l' -Loption (fichiers sans correspondance), provoquer sinon il affichera le contenu du fichier au lieu de son nom, comme dans votre exemple.

find . -type f -iname "*.java" -exec grep -L "something somethin" {} \+
se ruer
la source
1
-La déjà la négociation, car cela signifie files _without_ match. Par conséquent, vous n'avez pas besoin d' -voption ici.
rush
3
pas avec le supplément + à la fin.
lynxlynxlynx
2
@ user946850 chaque fois que j'écris, find -exec \+quelqu'un m'écrit qu'il vaut mieux utiliser xargs. pourquoi personne ne regarde l'homme avant d'écrire un commentaire? (:
précipitez-vous le
5
@ user946850 -exec ... {} \+n'est pas équivalent à xargs. Veuillez lire la documentation de findutils! (J'ai travaillé assez dur dessus!)
James Youngman
2
@ user946850 oui. L'une des différences est que (par défaut) xargstraite son entrée et sépare les arguments sur l'espace blanc. Les devis sont également spéciaux (par défaut) pour xargs. Aucune de ces choses n'est vraie -exec ... {} +. Les anciennes versions de xargsconsidéraient le trait de soulignement comme un indicateur EOF, mais ce n'est plus le cas.
James Youngman
7

Vous l'avez presque vraiment ...

find . -type f -iname "*.java" -print0 | xargs -0 grep -v "something something"

Le point '.' dit de commencer à partir d'ici. (le vôtre implique .. mais ne présumez jamais).

-iname utilise la recherche insensible à la casse, juste au cas où (ou juste en aucun cas).
-print0 envoie les noms de fichiers à xargs avec un caractère \ x00 de fin, ce qui évite les problèmes avec les noms de fichiers contenant des espaces.

le '-0' sur xargs indique qu'il faut s'attendre à des noms de fichiers se terminant par \ x00 au lieu de retours.

et votre commande grep ...

J'ai presque compris.


ÉDITER::

Depuis votre mise à jour:

find . -type f -iname "*pb.java" -print0 | xargs -0 grep -iL "something"

devrait aider. (Ajouté -L de la réponse de @ rush, bon travail)

J'ai l'idée que votre grep a besoin de l'option '-i' ou d'être moins explicite.

Essayez la commande en plusieurs parties ... CE nom de fichier de sortie semble-t-il correct?

find . -type f -iname "*pb.java"

Si c'est le cas, votre problème est probablement soit votre modèle de recherche grep ne correspond pas (erreur d'orthographe? Ça arrive!), Soit il n'y a tout simplement pas de correspondance.

Pire cas absolu:

grep -riL "something" *

fera BEAUCOUP plus de travail pour tout rechercher, mais devrait vous donner une sortie.

lornix
la source
J'ai essayé vos modifications et je n'obtiens toujours pas le résultat que j'attends. Je vais essayer de mettre à jour la question pour la rendre plus claire.
Hyangelo
Si l'auteur de la question veut simplement trouver les noms de fichiers, le grep ne devrait-il pas être 'grep -l -v'?
Bruce Ediger
il recherche des contenus spécifiques dans les fichiers * .java
lornix
xargs -0 grep -v "something something"devrait être xargs -0 grep -v "something something" /dev/nullautrement, vous obtiendrez des résultats étranges lorsque find ne produit aucun fichier correspondant.
James Youngman
{Grin} ouais, quelque part là-dedans, la logique est devenue tout poilue. Rien de tel qu'un test multiple de fausse logique inversée pour vous faire mal à la tête.
lornix
4

L'ordinateur est un ordinateur: il fait ce que vous lui avez dit au lieu de ce que vous vouliez qu'il fasse.

grep -v "something something"imprime toutes les lignes qui ne contiennent pas something something. Par exemple, il imprime deux lignes parmi les trois suivantes:

hello world
this is something something
something else

Pour imprimer des fichiers qui ne contiennent extends SomethingSomethingnulle part, utilisez l' -Loption:

grep -L -E 'extends[[:space:]]+SomethingSomething' FILENAME…

Certaines versions de grep n'ont pas cette -Loption (elle n'est pas spécifiée par POSIX ). Si le vôtre ne le fait pas, ne l'imprimez rien et utilisez le code de retour pour que le shell appelant fasse ce qu'il devrait faire à la place.

grep -q -E 'extends[[:space:]]+SomethingSomething' FILENAME ||
echo "$FILENAME"

Vous pouvez également utiliser awk.

awk '
    FNR == 1 && NR != 1 && !found { print fn }
    FNR == 1 { fn = FILENAME; found = 0; }
    /extends[[:space:]]+SomethingSomething/ { found = 1 }
    END { if (fn != "" && !found) print fn }
'

Sur Linux ou Cygwin (ou tout autre système avec GNU grep), vous n'avez pas besoin d'utiliser find, car il grepest capable de se reproduire.

grep -R --include='*.java' -L -E 'extends[[:space:]]+SomethingSomething'

Si votre shell est ksh ou bash ou zsh, vous pouvez faire en sorte que le shell fasse correspondre le nom de fichier. Sur bash, lancez d' set -o globstarabord (vous pouvez le mettre dans votre ~/.bashrc).

grep -L -E 'extends[[:space:]]+SomethingSomething' **/*.java
Gilles 'SO- arrête d'être méchant'
la source
Wow c'est encore mieux. J'utilisais 'extend (/ s) + SomethingSomething' qui semblait fonctionner pour autant que je sache. Y a-t-il une différence avec cette syntaxe avec celle spécifiée dans la version Extended RegEx?
Hyangelo
@Hyangelo \sest une extension GNU grep, avec laquelle je pense est synonyme [[:space:]].
Gilles 'SO- arrête d'être méchant'