Перевага перенаправлення stdin і stdout у Bash


9

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

cmd1 < cmd2 > cmd3

Чи перекладається це на:

(cmd1 < cmd2) > cmd3

Або

cmd1 < (cmd2 > cmd3)

Відповіді:


11

Стандарт POSIX визначає, що перенаправлення оболонки відбувається зліва направо; тобто порядок значний:

Конструкція 2>&1часто використовується для перенаправлення стандартної помилки на той самий файл, що і стандартний вихід. Оскільки переадресації відбуваються починаючи до кінця, порядок переадресацій є значним. Наприклад:

ls > foo 2>&1

спрямовує як стандартний вихід, так і стандартну помилку у файл foo. Однак:

ls 2>&1 > foo

тільки спрямовує стандартний вихід у файл, fooтому що стандартна помилка дублюється як стандартний вихід до того, як стандартний вихід буде спрямований у файл foo.

bash діє відповідно до цієї частини стандарту:

$ ls doesnotexist > foo 2>&1
$ cat foo
ls: cannot access doesnotexist: No such file or directory
$ ls doesnotexist 2>&1 > foo
ls: cannot access doesnotexist: No such file or directory
$ cat foo
$ 

Що стосується трубопроводів:

Оскільки призначення трубопроводу стандартного вводу або стандартного виходу або обох відбувається перед перенаправленням, його можна змінити шляхом перенаправлення. Наприклад:

$ command1 2>&1 | command2

посилає як стандартний вихід, так і стандартну помилку command1на стандартний вхід command2.


Це передбачає, що оболонка Bash сумісна з POSIX.
fpmurphy

1
Я не отримую цього. Оскільки ви сказали, що порядок знаходиться зліва направо, не слід ls > foo 2>&1означати перенаправлення stdout в foo, а потім перенаправлення stderr на stdout. Тож це не повинно працювати. Аналогічно повинна діяти друга команда. Що я тут пропускаю?
Діпак Міттал

1
@fpmurphy, bashяк правило, сумісний з POSIX, за винятком ситуацій, описаних тут , де bashповедінка за замовчуванням відрізняється. Щоб зробити bashвідповідність більше, ви можете скористатися --posixопцією.
Метт Еккерт

@dpacmittal Перший приклад, ls > foo 2>&1працює так: спочатку стандартний вихід переспрямовується на foo, потім стандартна помилка перенаправляється на стандартний вихід, який зараз є файлом foo. Другий приклад, ls 2>&1 > fooпрацює так: стандартна помилка перенаправляється на стандартний вихід до перенаправлення стандартного виводу foo, тому стандартна помилка лунає локально, а не спрямовується на файл.
Метт Екерт

4
@dpacmittal .. ls 2>&1 >foo Можливо, ви можете подумати про це так. stderr з 'ls' переспрямовується на stdout. Це станеться! Він буде йти туди , де стандартний висновок в даний час призначені йти, незалежно від будь - яких подальших вказівок , що стосуються стандартний висновок .. (бо це його головний / перша директива ) .. Тоді разом прийшли ще директиву , яка говорить , що стандартний висновок буде йти на «Foo», і це так ... Пам’ятайте: stderr не перетворюється на фактичний стан stdout .. Він просто переходить до місця, куди stdout був призначений під час дії директиви. (наприклад, термінал)
Peter.O

4

Гадаю, ні. Пара в дужках означає під оболонку. Але в цьому випадку жодна підрозділ не буде запущено через перенаправлення. Bash просто подає cmd2в stdin і подає stdout в cmd3.

Я думаю, ти маєш на увазі щось подібне cmd1 | cmd2 | cmd3? Тому що ваші cmd2і, cmd3як правило, звичайні файли замість "cmds".

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