Utilisation de grep avec pipe et esperluette pour filtrer les erreurs de find

22

J'utilise cygwin pour trouver un fichier sur le cygdrive.

Cependant, je dois supprimer les messages d'autorisation refusée (sinon les résultats sont masqués dans les messages d'erreur). La commande suivante fonctionne:

find -name 'myfile.*' |& grep -v "Permission denied"

Je ne comprends pas pourquoi l'esperluette doit être placée dans cette commande, se serait attendu à ce que cela fonctionne mais ce n'est pas le cas.

find -name 'myfile.*' | grep -v "Permission denied"

Veuillez expliquer la signification de l'esperluette.

Henrik K
la source

Réponses:

24

Dans les systèmes de type Unix, il existe deux chemins de sortie qui, s'ils ne sont pas modifiés, enverront la sortie à votre écran. L'erreur standard (ou stderr) est celle qui capture la plupart des échecs et des conditions d'erreur.

Pour transmettre le message d'autorisation refusée dans le stderr au même flux de sortie que "sortie régulière", vous devez combiner les deux. Dans votre exemple, pour que votre grep -vordinateur fonctionne correctement, vous combinez stdout (sortie standard) et stderr avec la syntaxe arcane que vous voyez.

Dans la section 3.2.2 Pipelines du manuel GNU Bash :

Si « |&» est utilisé, l'erreur standard de command1 , en plus de sa sortie standard, est connectée à l'entrée standard de command2 via le tuyau; c'est un raccourci pour 2>&1 |. Cette redirection implicite de l'erreur standard vers la sortie standard est effectuée après toutes les redirections spécifiées par la commande.

De plus, comme le souligne geirha, si vous voulez simplement vous débarrasser de la sortie stderr, vous voudriez faire quelque chose comme

find -name 'myfile.*' 2> /dev/null

ou peut-être

find -name 'myfile.*' 2> /tmp/errorlog

Et notez que si vous avez des chaînes de commandes, telles que la findtransmission de sa sortie, xargsvous devrez mettre le pipeline entier de commandes entre parenthèses pour capturer la sortie de tous les composants de la commande. Par exemple,

(find | egrep ^[RS].[0-9]+/.svg] | xargs head -1 )  2> /dev/null

Si vous avez omis les parenthèses, et avez fait cela à la place -

find | egrep ^[RS].[0-9]+/.svg] | xargs head -1 2> /dev/null

vous verrez toujours des erreurs d'autorisation refusée de la recherche ou egrep, mais stderr serait redirigé pour xargs.

Comme vous l'avez vu, vous ne jeterez probablement le stderr qu'après avoir vu son contenu pendant un test.

Notez qu'avec GNU findet pour autant que je sache, tout compatible POSIX find, l' -printoption est implicite. Vous pouvez toujours le fournir explicitement si vous le souhaitez.

belacqua
la source
Semble être uniquement bash4 + wiki.bash-hackers.org/bash4#redirection
Luke Exton
1
@LukeExton Oui. Dans d'autres shells, 2>&1 |peut être utilisé à la place de |&(c.-à-d., On peut rediriger explicitement stderr vers stdout, puis le rediriger vers la commande suivante du pipeline).
Eliah Kagan
2> >( grep filter )est également pratique
user1133275