Sowohl stdout als auch stderr in bash leiten?

156

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 (wird stattdessen an die Datei angehängt, wie Adrian klarstellte).

Was ist der einfachste Weg, um dasselbe zu erreichen, aber stattdessen zu einem anderen Befehl zu leiten?

Zum Beispiel in dieser Zeile:

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

Ich möchte, dass der grep sowohl in stdout als auch in stderr mit den Inhalten übereinstimmt (effektiv, lassen Sie sie zu einem Stream kombinieren).

Hinweis : Bei dieser Frage geht es um Rohrleitungen, nicht um Weiterleitungen. Es handelt sich also nicht um ein Duplikat der Frage, deren Duplikat derzeit markiert ist.

Andrew Ferrier
quelle
In der zweiten Antwort ( stackoverflow.com/a/637834/1129642 ) auf die verknüpfte Frage finden Sie Informationen zur korrekten Weiterleitung von stdout und stderr. Keine Notwendigkeit für eine andere Frage.
Marki555
4
@triplee Kein genaues Duplikat, oder? Pipe vs. Weiterleiten in Datei?
Benjamin W.
@BenjaminW Dort gibt es mindestens eine Antwort, die beide Szenarien löst, obwohl dies 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 zusammenzuführen - oder im schlimmsten Fall sogar eine völlig neue Kanonik für dieses Thema erstellen. Wenn Sie einen besseren Betrüger finden, schlagen Sie ihn auf jeden Fall vor. Danke im Voraus.
Tripleee
12
@tripleee Löst, ja, aber keine der Antworten verwendet die |&Verknüpfung, die meiner Meinung nach die mit Abstand bequemste Lösung ist, um "sowohl stdout als auch stderr in eine Pipe umzuleiten".
Benjamin W.
3
Dies ist kein Duplikat der verknüpften Frage, und es war nicht klar, dass Markos Antwort das tat, was ich wollte. Außerdem wird | & nicht erwähnt. Abstimmung zur Wiedereröffnung.
Martin Bonner unterstützt Monica

Antworten:

163

(Beachten Sie, dass an eine Datei &>>file angehängt wird , während eine zuvor vorhandene Datei &>umgeleitet und überschrieben wird .)

Zu kombinieren stdoutund stderrSie würden das letztere mit dem ersteren auf das erstere umleiten 2>&1. Dadurch wird stderr (Dateideskriptor 2) zu stdout (Dateideskriptor 1) umgeleitet, z.

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

stdoutgeht zu stdout, stderrgeht zu stderr. grepsieht nur stdout, stderrdruckt daher auf das Terminal.

Andererseits:

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

Leitet stderr nach dem Schreiben in stdout und stderr 2>&1zurück zu stdout und grepsieht beide Zeichenfolgen auf stdin, wodurch beide herausgefiltert werden.

Weitere Informationen zur Weiterleitung finden Sie hier .

Zu Ihrem Beispiel (POSIX):

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

oder mit >=bash-4:

cmd-doesnt-respect-difference-between-stdout-and-stderr |& grep -i SomeError
Adrian Frühwirth
quelle
Danke für die Klarstellung am &>>. Ich habe meine Frage korrigiert.
Andrew Ferrier
18
Ich habe Ihr Beispiel zu meiner Antwort hinzugefügt, nur für den Fall, dass es anhand meiner Beispiele nicht offensichtlich war. Als Randnotiz können Sie |&anstelle von auch die Bash-spezifische verwenden 2>&1 |.
Adrian Frühwirth
13
Randnotiz zu der |&von @ AdrianFrühwirth für zukünftige Leser vorgeschlagenen Verknüpfung : Diese Funktion wird nur mit bashVersion 4+ unterstützt. Wenn Sie 3 oder weniger verwenden, müssen Sie dabei bleiben 2>&1 |.
Tomocafe
3
Die Bash-Umleitung wird hier sehr gut erklärt . @ AdrianFrühwirth hat gute Arbeit geleistet, der eingefügte Link geht noch weiter. Manchmal wünschte ich mir, die offizielle Bash-Dokumentation wäre so gut.
David Andreoletti
112

Bash hat eine Abkürzung für 2>&1 |, nämlich |&sowohl stdout als auch stderr (siehe Handbuch ):

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

Dies wurde in Bash 4.0 eingeführt, siehe Versionshinweise .

Benjamin W.
quelle
Vielen Dank, dass Sie dies der Vollständigkeit halber hinzugefügt haben. Ich werde die andere Antwort korrekt halten, da viele Leute immer noch Bash vor 4.0 verwenden. Das ist aber nützlich.
Andrew Ferrier
9
Vor allem vielleicht ist der Bash, der unter macOS ausgeliefert wird, zu alt, um dies zu unterstützen.
Flimm
@ Flimm, aber der zsh ist nicht
Trenton
1
Da ksh | & für coproc verwendet, scheint dies eine schlechte Wahl für eine unnötige Abkürzung zu sein. Ich hasse es, Zeilen mit einem Stapel Dups und Weiterleitungen genauso zu sehen wie der nächste Typ, aber es gibt etwas zu sagen, um explizit zu sein ... und ich entschuldige mich, dass dieser Kommentar nicht viel hinzufügt. Ich wollte nur Abneigung gegen die Kurzschrift ausdrücken, ohne eine wirklich hilfreiche Antwort herabzustimmen, weil es gut ist, dass die Leute das sehen. Ich wusste das nicht, also danke, dass du mich darauf aufmerksam gemacht hast.
Paul Hodges
@PaulHodges Ich stimme zu, dass es nicht portabel ist - ich verwende es hauptsächlich für interaktive Bash-Sitzungen, um nicht zu viel zu tippen.
Benjamin W.