Трубопровод как stdout, так и stderr в bash?

Похоже, что более новые версии bash имеют оператор &>, который (если я правильно понимаю) перенаправляет как stdout, так и stderr в файл (&>> вместо этого добавляется к файлу, как пояснил Адриан).

Какой самый простой способ достичь того же, но вместо этого переходить к другой команде?

Например, в этой строке:

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

Я хочу, чтобы grep соответствовал содержимому как в stdout, так и в stderr (эффективно, объединив их в один поток).

Примечание: этот вопрос задает вопрос о трубопроводе, а не о перенаправлении, поэтому он не является дубликатом вопроса, который в настоящее время отмечен как дубликат.

Ответ 1

(Обратите внимание, что &>>file присоединяется к файлу, а &> будет перенаправлять и перезаписывать ранее существующий файл.)

Чтобы объединить stdout и stderr, вы переадресовываете последнее в первое, используя 2>&1. Это перенаправляет stderr (дескриптор файла 2) в stdout (дескриптор файла 1), например:

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

stdout переходит в stdout, stderr переходит в stderr. grep видит только stdout, поэтому stderr выводит на терминал.

С другой стороны:

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

После записи в stdout и stderr, 2>&1 перенаправляет stderr обратно в stdout и grep видит обе строки на stdin, таким образом отфильтровывает оба.

Подробнее о перенаправлении здесь.

Что касается вашего примера (POSIX):

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

или, используя >=bash-4:

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

Ответ 2

Bash имеет сокращенное обозначение 2>&1 |, а именно |&, которое передает как stdout, так и stderr (см. manual):

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

Это было представлено в Bash 4.0, см. примечания к выпуску.