Как понять порядок перенаправления вывода? [Дубликат]

10

Итак, я пытаюсь научиться передавать стандартное и стандартное err в разные области.

Предположим, что у меня есть папка с here.txt .

Итак, если я делаю

ls here.txt not-here.txt  1>out  2>&1

Так как here.txt присутствует, у меня будет некоторый вывод, чтобы направить файл out , но поскольку not-here.txt не существует, ошибка будет отправлена ​​через стандартную ошибку, которую я перенаправляю на стандартный с 2>&1 .

Однако почему это не работает:

ls here.txt not-here.txt 2>&1 1>out

Кажется, работает только, если я перенаправляю после стандартной инструкции? Почему?

    
задан Aruka J 24.09.2017 в 15:33
источник

3 ответа

5

Порядок переназначений значителен . Например, команда

ls > dirlist 2>&1

направляет как стандартный вывод, так и стандартную ошибку в файл dirlist, а команда

ls 2>&1 > dirlist

направляет только стандартный вывод в файл dirlist, поскольку стандартная ошибка дублируется от стандартного вывода (как правило, все еще указывает на окно терминала), прежде чем стандартный вывод был перенаправлен на dirlist.

Сначала это может показаться контр-интуитивным, но, подумав об этом, мы можем это понять.

Вы найдете это объяснение в man bash , в главе о перенаправлении,

  

ПЕРЕКВАЛИФИКАЦИИ

     

Перед выполнением команды его ввод и вывод могут быть перенаправлены с использованием специальной нотации, интерпретируемой оболочкой. Перенаправление позволяет копировать файлы команд, дублировать, открывать, закрывать, делать ссылки на разные файлы и изменять файлы, с которых команда считывает и записывает. Перенаправление также может использоваться для изменения файлов файлов в текущей среде выполнения оболочки. Следующие операторы перенаправления могут предшествовать или появляться в любой точке простой команды или могут следовать за командой. Перенаправления обрабатываются в том порядке, в котором они появляются, слева направо.

     

Каждой перенаправлению, которой может предшествовать номер дескриптора файла, может предшествовать слово формы {varname} . В этом случае для каждого оператора перенаправления, кроме >&- и <&- , оболочка будет выделять файловый дескриптор, который больше или равен 10, и назначить его varname . Если >&- или <&- предшествует {varname} , значение varname определяет дескриптор файла для закрытия.

     

В следующих описаниях, если номер дескриптора файла опущен, а первым символом оператора перенаправления является < , перенаправление относится к стандартному вводу (дескриптор файла 0). Если первым символом оператора перенаправления является > , перенаправление относится к стандартным выводам (дескриптор файла 1).

     

Слово, следующее за оператором перенаправления в следующих описаниях, если не указано иначе, подвергается расширению скобки, расширению тильды, расширению параметров и переменных, замене команд, арифметическому расширению, удалению цитат, расширению пути и разбиению слов. Если он расширяется до нескольких слов, bash сообщает об ошибке.

     

Обратите внимание, что порядок перенаправления значителен. Например, команда

ls > dirlist 2>&1
     

направляет как стандартный вывод, так и стандартную ошибку в файл dirlist , а команда

ls 2>&1 > dirlist
     

направляет только стандартный вывод в файл dirlist , поскольку стандартная ошибка дублируется от стандартного вывода до того, как стандартный вывод был перенаправлен на dirlist .

Изменить: следующие строки командной строки могут объяснить, что происходит

Подготовка

[email protected]:~$ touch qwerty;rm asdf
rm: cannot remove 'asdf': No such file or directory

Запустите команду списка для одного существующего файла и одного несуществующего файла

[email protected]:~$ ls qwerty asdf
ls: cannot access 'asdf': No such file or directory
qwerty

Перенаправить вывод ошибки перед перенаправлением стандартного вывода. Только стандартный вывод перенаправляется в выходной файл.

[email protected]:~$ ls qwerty asdf 2>&1 > output-file ;echo '---';cat output-file 
ls: cannot access 'asdf': No such file or directory
---
qwerty

Перенаправить вывод ошибки после перенаправления стандартного вывода. Как выход ошибки, так и стандартный вывод перенаправляются в выходной файл.

[email protected]:~$ ls qwerty asdf > output-file 2>&1 ;echo '---';cat output-file
---
ls: cannot access 'asdf': No such file or directory
qwerty

Токен &> может использоваться для перенаправления стандартной ошибки и стандартного вывода. Он может использоваться в bash , но может быть недоступен в других оболочках.

[email protected]:~$ ls qwerty asdf &> output-file ;echo '---';cat output-file
---
ls: cannot access 'asdf': No such file or directory
qwerty
[email protected]:~$ 
    
ответ дан sudodus 24.09.2017 в 15:57
источник
3
  • 2>x означает, что имя файла x получит данные, записанные в дескриптор 2 (также известный как stderr, стандартная ошибка)
  • ... но когда x указано как &1 , это не означает «всегда следует за 1 »; это означает "скопировать текущие свойства 1 (а затем оставить его в покое)" .
  • Перенаправления применяются в том же порядке, что и в командной строке, но до фактического выполнения.

Вот почему 2>&1 1>whatever выводит stderr на терминал.

Вот почему find / -name mylostfile.txt 3>&1 1>&2 2>&3 | grep -v 'Permission denied' обменивает stderr и stderr, так что вы можете отфильтровать некоторые общие строки stderr, но все равно видите все stdout. (Дескриптор 3 здесь не используется программами).

    
ответ дан kubanczyk 24.09.2017 в 20:59
2

Среда встречает и устанавливает в порядке, в котором она видит вещь. В первом случае:

ls here.txt not-here.txt  1>out  2>&1

Выход перенаправляется, затем стандартная ошибка отправляется в одно и то же место.

Во втором случае

ls here.txt not-here.txt 2>&1 1>out

Стандартная выгрузка по-прежнему установлена ​​на терминал, поэтому стандартная ошибка отправляется на терминал. Оболочка уже установила стандартную ошибку.

    
ответ дан jpezz 24.09.2017 в 16:01