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


156

Здається, що новіші версії bash мають &>оператора, який (якщо я правильно розумію) перенаправляє як stdout, так і stderr у файл ( &>>додає файл замість цього, як уточнив Адріан).

Який найпростіший спосіб досягти того самого, але замість цього перейти до іншої команди?

Наприклад, у цьому рядку:

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

Я хотів би, щоб греп відповідав вмісту як в stdout, так і в stderr (ефективно, об'єднайте їх в один потік).

Примітка : це запитання задає питання про трубопроводи, а не про переадресацію - тому це не дублікат запитання, яке в даний час позначено як дублікат.


Дивіться другу відповідь ( stackoverflow.com/a/637834/1129642 ) на пов'язане запитання щодо правильного способу передачі як stdout, так і stderr. Не потрібно іншого питання.
Marki555

4
@triplee Не точний дублікат, чи не так? Труба проти перенаправлення на файл?
Benjamin W.

@BenjaminW Там є принаймні одна відповідь, яка вирішує обидва сценарії, хоча це не прийнята відповідь. Це досить поширене питання, тому ми могли, мабуть, знайти кращий дублікат або попросити модератора злити їх - або навіть, в гіршому випадку, створити абсолютно новий канонічний для цієї теми. Якщо ви знайдете кращу дупу, будь ласка, запропонуйте це. Заздалегідь спасибі.
tripleee

12
@tripleee Вирішує, але жодна з відповідей не використовує |&ярлик, який, на мою думку, є найбільш зручним рішенням для "перенаправлення як stdout, так і stderr на трубу".
Бенджамін В.

3
Це не дублікат пов’язаного питання, і не було зрозуміло, чи відповідь Марко зробив те, що я хотів. Крім того, в ньому не згадується | &. Голосування за повторне відкриття.
Мартін Боннер підтримує Моніку

Відповіді:


163

(Зауважте, що &>>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

Дякуємо за роз’яснення о &>>. Я виправив своє запитання.
Ендрю Фер’є

18
Я додав ваш приклад до своєї відповіді, про всяк випадок, коли це було очевидно на основі моїх прикладів. В якості побічної ноти ви також можете використовувати специфіку bash |&замість 2>&1 |.
Адріан Фрюхвірт

13
Побічна примітка про ярлик, |&запропонований @ AdrianFrühwirth для майбутніх читачів: ця функція підтримується лише bashверсією 4+. Якщо ви використовуєте 3 або нижче, вам доведеться дотримуватися 2>&1 |.
томокафе

3
Перенаправлення Баша тут дуже добре пояснено . @ AdrianFrühwirth зробив гарну роботу, вставлене посилання йде ще далі. Іноді я хочу, щоб офіційна документація Баша була такою доброю.
Девід Андреолетті

112

Bash має скорочення 2>&1 |, а саме |&, які труби як stdout, так і stderr (див. Інструкцію ):

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

Це було представлено в Bash 4.0, див. Примітки до випуску .


Дякуємо, що додали це для повноти. Я буду тримати іншу відповідь правильною, оскільки багато людей все ще використовують bash до 4.0. Але це корисно.
Ендрю Фер’є

9
Мабуть, особливо, що Bash, який розміщується на macOS, занадто старий, щоб підтримувати це.
Flimm

@Flimm, але zsh не
Трентон

1
Оскільки ksh використовує | & для coproc, це здається поганим вибором для зайвої скорочення. Я ненавиджу бачити рядки з купою дуп і перенаправлень стільки ж, скільки й наступний хлопець, але є що сказати, що явні .... Я просто хотів висловити неприємність до стенограми, не зводячи насправді корисної відповіді, бо добре, що люди це бачать. Я цього не знав, тому дякую за те, що мене зрозуміли.
Пол Ходжес

@PaulHodges Я погоджуюся, що це не портативно - мені в основному подобається використовувати його для інтерактивних сесій Bash, щоб уникнути занадто багато набору тексту.
Бенджамін В.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.