J'utilise ffmpeg pour obtenir les méta-informations d'un clip audio. Mais je suis incapable de le savoir.
$ ffmpeg -i 01-Daemon.mp3 |grep -i Duration
FFmpeg version SVN-r15261, Copyright (c) 2000-2008 Fabrice Bellard, et al.
configuration: --prefix=/usr --bindir=/usr/bin
--datadir=/usr/share/ffmpeg --incdir=/usr/include/ffmpeg --libdir=/usr/lib
--mandir=/usr/share/man --arch=i386 --extra-cflags=-O2
...
J'ai vérifié, cette sortie de ffmpeg est dirigée vers stderr.
$ ffmpeg -i 01-Daemon.mp3 2> /dev/null
Donc, je pense que grep est incapable de lire le flux d'erreur pour intercepter les lignes correspondantes. Comment pouvons-nous activer grep pour lire le flux d'erreur?
En utilisant le lien nixCraft , j'ai redirigé le flux d'erreur standard vers le flux de sortie standard, puis grep a fonctionné.
$ ffmpeg -i 01-Daemon.mp3 2>&1 | grep -i Duration
Duration: 01:15:12.33, start: 0.000000, bitrate: 64 kb/s
Mais que se passe-t-il si nous ne voulons pas rediriger stderr vers stdout?
grep
io-redirection
ffmpeg
Andrew-Dufresne
la source
la source
grep
cela ne peut fonctionner que sur stdout (bien que je ne puisse pas trouver la source canonique pour la sauvegarder), ce qui signifie que tout flux doit d'abord être converti en stdout.grep
ne peut fonctionner que sur stdin. C'est le canal créé par le shell qui relie stdin de grep à la sortie standard de l'autre commande. Et le shell ne peut connecter qu'un stdout à un stdin.Réponses:
Si vous utilisez,
bash
pourquoi ne pas utiliser des pipes anonymes, en résumé, ce que phunehehe a dit:ffmpeg -i 01-Daemon.mp3 2> >(grep -i Duration)
la source
cp
sortiecp -r dir* to 2> >(grep -v "svn")
>&2
command 2> >(grep something >&2)
2>
redirige stderr vers un fichier, je comprends ça. Cela lit à partir du fichier>(grep -i Duration)
. Mais le fichier n'est jamais stocké? Comment appelle-t-on cette technique pour en savoir plus à ce sujet?Aucun des shells habituels (même zsh) n'autorise les pipes autres que de stdout à stdin. Mais tous les shells de style Bourne prennent en charge la réaffectation de descripteur de fichier (comme dans
1>&2
). Vous pouvez donc temporairement renvoyer stdout sur fd 3 et stderr sur stdout, puis remettre fd 3 sur stdout. Sistuff
produit une sortie sur stdout et une sortie sur stderr, et que vous souhaitez appliquerfilter
sur la sortie d'erreur sans modifier la sortie standard, vous pouvez l'utiliser{ stuff 2>&1 1>&3 | filter 1>&2; } 3>&1
.la source
pipestatus
cela aiderait peut - êtreset -o pipefail
peut également être utile ici, selon ce que vous voulez faire avec le statut d'erreur. (Par exemple, si vous avezset -e
activé l'échec pour toute erreur, vous voudrez probablementset -o pipefail
aussi.)set -e
activé pour échouer sur les erreurs.rc
coquille permet la tuyauterie stderr. Voir ma réponse ci-dessous.Ceci est similaire à "l'astuce de fichier temp" de phunehehe, mais utilise plutôt un canal nommé, ce qui vous permet d'obtenir des résultats un peu plus proches du moment de leur sortie, ce qui peut être pratique pour les commandes de longue durée:
Dans cette construction, stderr sera dirigé vers le tuyau nommé "mypipe". Comme il
grep
a été appelé avec un argument de fichier, STDIN ne sera pas saisi. Malheureusement, vous devrez toujours nettoyer le tuyau nommé une fois que vous aurez terminé.Si vous utilisez Bash 4, il existe une syntaxe de raccourci pour
command1 2>&1 | command2
, qui estcommand1 |& command2
. Cependant, je pense que ceci est purement un raccourci de syntaxe, vous redirigez toujours STDERR vers STDOUT.la source
|&
syntaxe est parfaite pour nettoyer les traces de pile Ruby stderr gonflées. Je peux enfin grep ceux sans trop de soucis.Les réponses de Gilles et Stefan Lasiewski sont bonnes, mais cette méthode est plus simple:
Je suppose que vous ne voulez pas que
ffmpeg's
stdout soit imprimé.Comment ça fonctionne:
la source
Voir ci-dessous pour le script utilisé dans ces tests.
Grep ne peut fonctionner que sur stdin, vous devez donc convertir le flux stderr sous une forme que Grep peut analyser.
Normalement, stdout et stderr sont tous deux imprimés sur votre écran:
Pour masquer stdout, mais toujours imprimer stderr, procédez comme suit:
Mais grep ne fonctionnera pas sur stderr! Vous pouvez vous attendre à ce que la commande suivante supprime les lignes contenant «err», mais ce n'est pas le cas.
Voici la solution.
La syntaxe Bash suivante cachera la sortie sur stdout, mais affichera toujours stderr. Nous lançons d’abord stdout dans / dev / null, puis nous convertissons stderr en stdout, car les pipes Unix ne fonctionneront que sur stdout. Vous pouvez toujours grep le texte.
(Notez que la commande ci-dessus est différente alors
./command >/dev/null 2>&1
, ce qui est une commande très courante).Voici le script utilisé pour les tests. Ceci affiche une ligne sur stdout et une ligne sur stderr:
la source
./stdout-stderr.sh 2>&1 >/dev/null | grep err
.Lorsque vous dirigez la sortie d'une commande vers une autre (en utilisant
|
), vous ne faites que rediriger la sortie standard. Cela devrait donc expliquer pourquoine sort pas ce que vous vouliez (ça marche quand même).
Si vous ne souhaitez pas rediriger la sortie d'erreur vers la sortie standard, vous pouvez rediriger la sortie d'erreur vers un fichier, puis corrigez-la ultérieurement.
la source
it does work, though
, vous voulez dire que cela fonctionne sur votre machine? Deuxièmement, comme vous l'avez fait remarquer en utilisant un tuyau, nous ne pouvons que rediriger stdout. Je suis intéressé par une fonctionnalité de commande ou bash qui me permettra de rediriger stderr. (mais pas l'astuce de fichier temporaire)Vous pouvez échanger les flux. Cela vous permettrait d'
grep
accéder au flux d'erreur standard d'origine tout en obtenant la sortie qui était à l'origine en sortie standard dans le terminal:Cela fonctionne en créant tout d'abord un nouveau descripteur de fichier (3) ouvert pour la sortie et en le configurant sur le flux d'erreur standard (
3>&2
). Ensuite, nous redirigeons l'erreur type vers la sortie standard (2>&1
). Enfin, la sortie standard est redirigée vers l'erreur standard d'origine et le nouveau descripteur de fichier est fermé (1>&3-
).Dans ton cas:
Le tester:
la source
J'aime utiliser la
rc
coquille dans ce cas.Installez d'abord le paquet (moins de 1 Mo).
Voici un exemple de la façon dont vous écarteriez
stdout
et dirigeriezstderr
vers grep dansrc
:find /proc/ >[1] /dev/null |[2] grep task
Vous pouvez le faire sans quitter Bash:
rc -c 'find /proc/ >[1] /dev/null |[2] grep task'
Comme vous l'avez peut-être remarqué, la syntaxe est simple, ce qui en fait la solution que je préfère.
Vous pouvez spécifier le descripteur de fichier que vous souhaitez transférer entre crochets, juste après le caractère de canal.
Les descripteurs de fichier standard sont numérotés comme tels:
la source
Une variante de l'exemple de sous-processus bash:
faire écho deux lignes à stderr et tee stderr à un fichier, grepez le tee et redirigez-vous vers stdout
stdout:
des.erreurs (par exemple, stderr):
la source
essayez cette commande
ceva -> juste un nom de variable (anglais = quelque chose)
la source
/tmp/$ceva
mieux que de jeter des fichiers temporaires dans le répertoire actuel - et vous supposez que le répertoire actuel est accessible en écriture.