2013-05-11 10 views
98

Es scheint, dass neuere Versionen von bash den Operator &> haben, der (wenn ich das richtig verstehe) sowohl stdout als auch stderr in eine Datei umleitet (&>> hängt stattdessen an die Datei, wie Adrian geklärt hat).Piping sowohl stdout und stderr in bash?

Was ist der einfachste Weg, um das Gleiche zu erreichen, sondern stattdessen einen anderen Befehl zu leiten?

Zum Beispiel in dieser Zeile:

cmd-doesnt-respect-difference-between-stdout-and-stderr | grep -i SomeError 

ich der grep auf Inhalt übereinstimmen möchte sowohl in stdout und stderr (effektiv, haben sie in einen Strom kombiniert).

Hinweis: diese Frage über Rohrleitungen zu fragen, nicht Umleiten - so ist es kein Duplikat der Frage ist es derzeit als Duplikat markiert ist.

+0

Siehe die zweite Antwort (https://stackoverflow.com/a/637834/1129642) auf die verknüpfte Frage für die richtige Art, Pipe sowohl stdout und stderr. Keine Notwendigkeit für eine andere Frage. – Marki555

+3

@triplee Nicht ein exaktes Duplikat, oder? Pipe vs. Redirect in Datei? –

+0

@BenjaminW Es gibt mindestens eine Antwort, die beide Szenarien löst, obwohl es nicht die akzeptierte Antwort ist.Dies ist eine ziemlich häufige Frage, daher könnten wir wahrscheinlich ein besseres Duplikat finden oder einen Moderator bitten, diese zusammenzufassen - oder im schlimmsten Fall sogar eine völlig neue Kanonistik für dieses Thema zu erstellen. Wenn Sie einen besseren Betrogenen finden, schlagen Sie ihn auf alle Fälle vor. Danke im Voraus. – tripleee

Antwort

114

(Beachten Sie, dass &>>file in eine Datei anhängt, während &> und eine zuvor vorhandene Datei überschreiben würde umleiten.)

stdout kombinieren und stderr Sie würden die letzteren zur ersteren mit 2>&1 umleiten. Diese Umleitungen Stderr (Dateideskriptor 2) in stdout (Dateideskriptor 1), z.B .:

$ { echo "stdout"; echo "stderr" 1>&2; } | grep -v std 
stderr 
$ 

stdout geht zu stdout, geht stderr zu Stderr. grep sieht nur stdout, daher stderr druckt auf das Terminal.

Auf der anderen Seite:

$ { echo "stdout"; echo "stderr" 1>&2; } 2>&1 | grep -v std 
$ 

Nachdem beide auf stdout und stderr zu schreiben, leitet 2>&1 Stderr zurück auf stdout und grep sieht beide Saiten auf stdin, filtert somit beide aus.

Sie können mehr über Umleitung here lesen.

In Bezug auf Ihrem Beispiel (POSIX):

cmd-doesnt-respect-difference-between-stdout-and-stderr 2>&1 | grep -i SomeError 

oder unter Verwendung von >=bash-4:

cmd-doesnt-respect-difference-between-stdout-and-stderr |& grep -i SomeError 
+0

Danke für die Erläuterung zu '& >>'. Ich habe meine Frage korrigiert. –

+14

Ich habe Ihr Beispiel zu meiner Antwort hinzugefügt, nur für den Fall, dass es aufgrund meiner Beispiele nicht offensichtlich war. Als Randnotiz können Sie auch das bash-spezifische '| &' anstelle von '2> & 1 |' verwenden. –

+0

Danke für die Klarstellung. Hilfreiche Antwort, danke. –

46

heftigen Schlag hat eine Abkürzung für 2>&1 |, nämlich |&, die Rohre sowohl stdout und stderr (siehe manual):

cmd-doesnt-respect-difference-between-stdout-and-stderr |& grep -i SomeError 

Dies wurde in Bash 4.0 eingeführt, siehe release notes.

+0

Vielen Dank für die Ergänzung der Vollständigkeit. Ich werde die andere Antwort korrekt halten, da viele Leute immer noch bash pre-4.0 verwenden. Aber das ist nützlich. –

+3

Vor allem vielleicht ist die Bash, die auf MacOS ausgeliefert wird, zu alt, um dies zu unterstützen. – Flimm

+0

@Flimm aber die Zsh ist nicht – Trenton