Ich verwende ffmpeg, um die Metainformationen eines Audioclips abzurufen. Aber ich kann es nicht fassen.
$ 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
...
Ich habe überprüft, dass diese ffmpeg-Ausgabe an stderr gerichtet ist.
$ ffmpeg -i 01-Daemon.mp3 2> /dev/null
Daher denke ich, dass grep den Fehlerstrom nicht lesen kann, um übereinstimmende Zeilen abzufangen. Wie kann grep das Lesen von Fehlerströmen ermöglichen?
Unter Verwendung von nixCraft link habe ich den Standardfehlerstrom auf den Standardausgabestrom umgeleitet, dann hat grep funktioniert.
$ ffmpeg -i 01-Daemon.mp3 2>&1 | grep -i Duration
Duration: 01:15:12.33, start: 0.000000, bitrate: 64 kb/s
Was aber, wenn wir stderr nicht auf stdout umleiten wollen?
grep
io-redirection
ffmpeg
Andrew-Dufresne
quelle
quelle
grep
kann nur mit stdout funktionieren (obwohl ich die kanonische Quelle nicht finden kann, um das zu sichern), was bedeutet, dass jeder Stream zuerst in stdout konvertiert werden muss.grep
Kann nur mit stdin arbeiten. Es ist die Pipe, die von der Shell erstellt wurde und die die Standardeingabe von grep mit der Standardeingabe des anderen Befehls verbindet. Und die Shell kann nur einen stdout mit einem stdin verbinden.Antworten:
Wenn Sie
bash
anonyme Pipes verwenden, verwenden Sie im Wesentlichen die Abkürzung für das, was phunehehe sagte:ffmpeg -i 01-Daemon.mp3 2> >(grep -i Duration)
quelle
cp
Ausgabe zu überprüfencp -r dir* to 2> >(grep -v "svn")
>&2
, zum Beispielcommand 2> >(grep something >&2)
2>
leitet stderr in die Datei um, das verstehe ich. Dies liest aus der Datei>(grep -i Duration)
. Aber die Datei wird nie gespeichert? Wie heißt diese Technik, damit ich mehr darüber lesen kann?Keine der üblichen Schalen (sogar zsh) erlaubt andere Pfeifen als stdout bis stdin. Alle Shells im Bourne-Stil unterstützen jedoch die Neuzuweisung von Dateideskriptoren (wie in
1>&2
). Sie können also stdout vorübergehend auf fd 3 und stderr auf stdout umleiten und später fd 3 wieder auf stdout setzen. Wennstuff
eine Ausgabe auf stdout und eine Ausgabe auf stderr erzeugt wird und Siefilter
auf die Fehlerausgabe anwenden möchten, ohne die Standardausgabe zu verändern, können Sie verwenden{ stuff 2>&1 1>&3 | filter 1>&2; } 3>&1
.quelle
pipestatus
würde helfenset -o pipefail
kann auch hier hilfreich sein, je nachdem, was Sie mit dem Fehlerstatus machen möchten. (Wenn Sie beispielsweise aktiviert haben,set -e
um Fehler zu beheben, möchten Sie wahrscheinlichset -o pipefail
auch.)set -e
eingeschaltet, um bei Fehlern zu scheitern.rc
Schale ermöglicht die Verrohrung stderr. Siehe meine Antwort unten.Dies ähnelt dem "Temp-File-Trick" von phunehehe, verwendet jedoch stattdessen eine Named-Pipe, so dass Sie die Ergebnisse bei der Ausgabe etwas näher kommen lassen.
Bei dieser Konstruktion wird stderr auf die Pipe mit dem Namen "mypipe" gerichtet. Da
grep
mit einem Datei-Argument aufgerufen wurde, sucht es nicht nach STDIN für seine Eingabe. Leider müssen Sie diese Named Pipe immer noch bereinigen, wenn Sie fertig sind.Wenn Sie mit Bash 4, gibt es eine Abkürzung Syntax
command1 2>&1 | command2
, die istcommand1 |& command2
. Ich glaube jedoch, dass dies eine reine Syntaxverknüpfung ist. Sie leiten STDERR weiterhin an STDOUT um.quelle
|&
Syntax ist perfekt, um aufgeblähte Ruby-Stderr-Stack-Traces zu bereinigen. Ich kann diese endlich ohne allzu großen Aufwand greifen.Die Antworten von Gilles und Stefan Lasiewski sind beide gut, aber dieser Weg ist einfacher:
Ich gehe davon aus, dass Sie nicht wollen, dass etwas
ffmpeg's
gedruckt wird.Wie es funktioniert:
quelle
Das in diesen Tests verwendete Skript finden Sie weiter unten.
Grep kann nur mit stdin arbeiten, daher müssen Sie den stderr-Stream in eine Form konvertieren, die Grep parsen kann.
Normalerweise werden sowohl stdout als auch stderr auf Ihrem Bildschirm gedruckt:
Gehen Sie wie folgt vor, um stdout auszublenden, aber immer noch stderr zu drucken:
Aber grep funktioniert nicht auf stderr! Sie würden erwarten, dass der folgende Befehl Zeilen unterdrückt, die 'err' enthalten, dies jedoch nicht.
Hier ist die Lösung.
Die folgende Bash-Syntax verbirgt die Ausgabe in stdout, zeigt aber immer noch stderr an. Zuerst leiten wir stdout nach / dev / null weiter, dann konvertieren wir stderr nach stdout, da Unix-Pipes nur mit stdout arbeiten. Sie können den Text immer noch lesen.
(Beachten Sie, dass der obige Befehl dann anders ist
./command >/dev/null 2>&1
, was ein sehr häufiger Befehl ist).Hier ist das zum Testen verwendete Skript. Dies gibt eine Zeile an stdout und eine Zeile an stderr aus:
quelle
./stdout-stderr.sh 2>&1 >/dev/null | grep err
.Wenn Sie die Ausgabe eines Befehls an einen anderen
|
leiten (mit ), leiten Sie nur die Standardausgabe um. Das sollte also erklären, warumgibt nicht aus, was Sie wollten (es funktioniert jedoch).
Wenn Sie die Fehlerausgabe nicht in die Standardausgabe umleiten möchten, können Sie die Fehlerausgabe in eine Datei umleiten und später erneut abrufen
quelle
it does work, though
Sie meinen, es funktioniert auf Ihrer Maschine? Zweitens können wir, wie Sie mit pipe bereits betont haben, nur stdout umleiten. Ich bin an einem Befehl oder einer Bash-Funktion interessiert, mit der ich stderr umleiten kann. (aber nicht die temporäre Datei Trick)Sie können die Streams tauschen. Dies würde es Ihnen ermöglichen, zum
grep
ursprünglichen Standardfehlerstrom zurückzukehren, während Sie weiterhin die Ausgabe erhalten, die ursprünglich zur Standardausgabe im Terminal ging:Dies funktioniert, indem zuerst ein neuer Dateideskriptor (3) erstellt wird, der für die Ausgabe geöffnet ist, und auf den Standardfehlerstrom (
3>&2
) gesetzt wird. Dann leiten wir Standardfehler zur Standardausgabe (2>&1
) um. Schließlich wird die Standardausgabe auf den ursprünglichen Standardfehler umgeleitet und der neue Dateideskriptor geschlossen (1>&3-
).In deinem Fall:
Testen Sie es:
quelle
Ich benutze
rc
in diesem Fall gerne die Shell.Installieren Sie zuerst das Paket (es ist weniger als 1 MB).
Dies ist ein Beispiel dafür, wie Sie verwerfen
stdout
undstderr
einlesen würdenrc
:find /proc/ >[1] /dev/null |[2] grep task
Sie können es tun, ohne Bash zu verlassen:
rc -c 'find /proc/ >[1] /dev/null |[2] grep task'
Wie Sie vielleicht bemerkt haben, ist die Syntax einfach und daher meine bevorzugte Lösung.
Sie können angeben, welcher Dateideskriptor in eckigen Klammern direkt nach dem Pipe-Zeichen eingefügt werden soll.
Standard-Dateideskriptoren sind wie folgt nummeriert:
quelle
Eine Variation des Bash-Unterprozess-Beispiels:
Echo zwei Zeilen zu stderr und tee stderr zu einer Datei, grep das Tee und Pipe zurück zu stdout
Standard:
Einige.Ladefehler (zB stderr):
quelle
versuche diesen Befehl
ceva -> nur ein Variablenname (englisch = etwas)
quelle
/tmp/$ceva
, besser als das aktuelle Verzeichnis mit temporären Dateien zu verunreinigen - und Sie gehen davon aus, dass das aktuelle Verzeichnis beschreibbar ist.