Pipowanie zarówno stdout, jak i stderr w bash?

156

Wygląda na to, że nowsze wersje basha mają &>operator, który (o ile dobrze rozumiem) przekierowuje zarówno stdout, jak i stderr do pliku ( &>>zamiast tego dołącza do pliku, jak wyjaśnił Adrian).

Jaki jest najprostszy sposób osiągnięcia tego samego, ale zamiast tego przekierowanie do innego polecenia?

Na przykład w tej linii:

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

Chciałbym, aby grep dopasował zawartość zarówno na stdout, jak i stderr (efektywnie, połącz je w jeden strumień).

Uwaga : to pytanie dotyczy potoku, a nie przekierowania - więc nie jest duplikatem pytania, które jest obecnie oznaczone jako duplikat.

Andrew Ferrier
źródło
Zobacz drugą odpowiedź ( stackoverflow.com/a/637834/1129642 ) w połączonym pytaniu, aby dowiedzieć się, jak prawidłowo potokować zarówno stdout, jak i stderr. Nie ma potrzeby zadawania kolejnego pytania.
Marki555,
4
@triplee Nie jest to dokładny duplikat, prawda? Potok czy przekierowanie do pliku?
Benjamin W.
@BenjaminW Jest tam co najmniej jedna odpowiedź, która rozwiązuje oba scenariusze, chociaż nie jest to akceptowana odpowiedź. Jest to dość częste pytanie, więc prawdopodobnie moglibyśmy znaleźć lepszy duplikat lub poprosić moderatora o ich scalenie - lub nawet, w najgorszym przypadku, stworzyć zupełnie nowy kanonik dla tego tematu. Jeśli znajdziesz lepszego naśladowcę, zdecydowanie to zaproponuj. Z góry dziękuję.
tripleee
12
@tripleee Rozwiązuje, tak, ale żadna z odpowiedzi nie używa |&skrótu, który moim zdaniem jest zdecydowanie najwygodniejszym rozwiązaniem do „przekierowania zarówno stdout, jak i stderr do potoku”.
Benjamin W.
3
To nie jest duplikat połączonego pytania i nie było jasne, czy odpowiedź Marko spełniła moje oczekiwania. Nie wspomina też o | &. Głosowanie za ponownym otwarciem.
Martin Bonner wspiera Monikę

Odpowiedzi:

163

(Zauważ, że &>>file dołączanie do pliku &>spowoduje przekierowanie i zastąpienie wcześniej istniejącego pliku).

Aby połączyć stdouti stderrprzekierować to drugie do pierwszego za pomocą 2>&1. To przekierowuje stderr (deskryptor pliku 2) do stdout (deskryptor pliku 1), np .:

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

stdoutidzie na stdout, stderridzie na stderr. greptylko widzi stdout, stąd stderrdrukuje do terminala.

Z drugiej strony:

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

Po zapisaniu zarówno na stdout, jak i stderr, 2>&1przekierowuje stderr z powrotem na stdout i grepwidzi oba ciągi na stdin, w ten sposób odfiltrowuje oba.

Więcej o przekierowaniu przeczytasz tutaj .

Odnośnie twojego przykładu (POSIX):

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

lub używając >=bash-4:

cmd-doesnt-respect-difference-between-stdout-and-stderr |& grep -i SomeError
Adrian Frühwirth
źródło
Dzięki za wyjaśnienie &>>. Poprawiłem swoje pytanie.
Andrew Ferrier
18
Dodałem twój przykład do mojej odpowiedzi, na wypadek gdyby nie było to oczywiste na podstawie moich podanych przykładów. Na marginesie, możesz również użyć specyficznego dla basha |&zamiast 2>&1 |.
Adrian Frühwirth
13
Uwaga boczna na temat skrótu |&zaproponowanego przez @ AdrianFrühwirth dla przyszłych czytelników: ta funkcja jest obsługiwana tylko w bashwersji 4+. Jeśli używasz 3 lub mniej, musisz się trzymać 2>&1 |.
tomocafe
3
Przekierowanie Bash jest tutaj bardzo dobrze wyjaśnione . @ AdrianFrühwirth wykonał dobrą robotę, wklejony link idzie jeszcze dalej. Czasami chciałbym, żeby oficjalna dokumentacja Basha była tak dobra.
David Andreoletti
112

Bash ma skrót dla 2>&1 |, a mianowicie |&, który potokuje zarówno stdout, jak i stderr (zobacz podręcznik ):

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

Zostało to wprowadzone w Bash 4.0, zobacz informacje o wydaniu .

Benjamin W.
źródło
Dzięki za dodanie tego dla kompletności. Druga odpowiedź pozostanie poprawna, ponieważ wielu ludzi nadal używa basha przed 4.0. Ale to jest przydatne.
Andrew Ferrier
9
Przede wszystkim być może Bash, który jest dostarczany w systemie MacOS, jest zbyt stary, aby to obsługiwać.
Flimm
@Flimm, ale zsh nie
Trenton
1
Ponieważ ksh używa | & dla coproc, wydaje się to złym wyborem dla niepotrzebnego skrótu. Nienawidzę widzieć wierszy ze stosem dupków i przekierowań tak samo jak następny facet, ale jest coś do powiedzenia, aby być wyraźnym ... i przepraszam, że ten komentarz nie wnosi wiele. Chciałem tylko wyrazić niechęć do stenogramów bez odrzucania faktycznie pomocnej odpowiedzi, ponieważ dobrze, że ludzie to widzą. Nie wiedziałem o tym, więc dziękuję za uświadomienie mi.
Paul Hodges
@PaulHodges Zgadzam się, że nie jest przenośny - głównie lubię używać go do interaktywnych sesji Bash, aby uniknąć zbyt dużego pisania.
Benjamin W.