bash
. Действительно, вроде всё понятно, но...Например, было непонятно, почему работает команда, перенаправляющая
stderr
в stdout
:ls *.txt *.err >file 2>&1
Но при этом не работает вот так:
ls *.txt *.err 2>&1 >file
И уж совсем китайской грамотой казалась строка:
cat file 3>&2 2>&1 1>&3
Да, мне понятно, что эта команда меняет местами потоки вывода
stderr
и stdout
. То, что выводилось в stdout
, теперь будет выводиться в stderr
и наоборот. Но почему именно так и никак иначе?..Всё оказалось не просто, а очень просто :) Спасибо замечательной книге "Unix Power Tools" издательства O'Reilly.
Дело в том, что оболочка, при разборе параметров командной строки, читает параметры строго слева направо. Этот факт кажется совсем неудивительным, но оказывается именно это правило оказывает влияние на результат обработки командной строки.
Разберем, как интерпретируется строка "
ls *.txt *.err >file 2>&1
":- параметр "
>file
" — означает "перенаправить стандартный поток вывода (stdout
) в файл c именемfile
"; - параметр "
2>&1
" — означает "перенаправить стандартный поток ошибок (2) в стандартный поток вывода (1). Но, так как стандартный поток вывода уже перенаправлен в файл, то и стандартный поток ошибок перенаправляется туда же.
А как интерпретируется строка "
ls *.txt *.err 2>&1 >file
"?- параметр "
2>&1
" — означает "перенаправить стандартный поток ошибок в стандартный поток вывода". На этот момент поток вывода (1) направляется в терминал, а значит, что поток ошибок тоже перенаправится в терминал. - параметр "
>file
" — означает "перенаправить стандартный поток вывода (stdout
) в файл c именемfile
".
После этого совсем не трудно понять, как работает команда "
cat file 3>&2 2>&1 1>&3
". Тут тоже все просто:- поток вывода 3 перенаправить туда же, куда выводится поток вывода 2 — в
stderr
; - поток вывода 2 перенаправить туда же, куда выводится поток 1 — в
stdout
; - поток вывода 1 перенаправить туда же, куда выводится поток 3 — в
stderr
stderr
и stdout
как будто меняются местами — поток 1 идет в stderr
, а поток 2 идет в stdout
.