Оператор перенаправления не работает должным образом - PullRequest
0 голосов
/ 05 августа 2020

У меня есть 2 файла в моем текущем каталоге: / home / tushar / Desktop

file1.txt
file4.txt

Итак, когда я нажимаю команду:

1. ls file{1..4}.txt

Вывод:

ls: cannot access 'file2.txt': No such file or directory
ls: cannot access 'file3.txt': No such file or directory
file1.txt  file4.txt

Теперь я перенаправляю stderr и stdout в файл res.txt, используя:

2. ls file{1..4}.txt 1>res.txt 2>res.txt

res.txt:

file1.txt
file4.txt
ile2.txt': No such file or directory
ls: cannot access 'file3.txt': No such file or directory

Выше мы видим, что часть содержимого stderr пропущена в файле res.txt.

Теперь я изменил свою команду на :

3. ls file{1..4}.txt 1>res.txt 2>&1

res.txt:

ls: cannot access 'file2.txt': No such file or directory
ls: cannot access 'file3.txt': No such file or directory
file1.txt
file4.txt

Обе приведенные выше команды точно такие же, за исключением 2-го я перенаправил stderr, где stdout перенаправляет с использованием дескриптора файла (& 1).

Теперь я знаю, что мне следует использовать команду , которая открывает res.txt в режиме добавления , как показано ниже:

4. ls file{1..4}.txt 1>>res.txt 2>&1
OR
5. ls file{1..4}.txt &> res.txt

но меня беспокоит:

Почему результаты cmd 2 и cmd 3 отличаются ?

Почему cmd 3 выводит правильный вывод даже без usi ng >> символ, но не cmd 2 ?

Ответы [ 4 ]

1 голос
/ 05 августа 2020

Для второго вопроса:

Потому что 2>&1 означает, что fd 2 является дубликатом fd (дескриптор файла) 1. Затем > или >> open 1 (stdin) в добавлении или в новом / усеченном режиме. Таким образом, они описывают две разные операции, используя один и тот же символ >, просто потому, что: 1- они работают с файловыми дескрипторами (> мог бы помнить это вместо нового символа, например, с участием $, 2- Это был недопустимый синтаксис перед добавлением такого расширения, поэтому значение будет уникальным.

Вопрос 1 сложнее. Вы открываете один и тот же файл дважды независимо, и программа видит их независимо, поэтому они могут иметь разные кеши и приоритеты. В общем: не делайте 2, но если вы это сделаете, вы должны выводить sh в каждой строке (и, возможно, сделать строку короткой). Вы можете увидеть что-то вроде 2 в журнале, но иногда вы также см. вывод двух смешанных и частично объединенных программ.

Я также не уверен, что 2. определен и доступен во всех POSIX-совместимых оболочках.

0 голосов
/ 05 августа 2020

Чтобы ответить на первый вопрос более подробно: когда вы запускаете ls file{1..4}.txt 1>res.txt 2>res.txt, он открывает res.txt дважды, независимо . Это означает, что каждый записывающий в него файловый дескриптор имеет разное представление о том, где он находится (его смещение или позиция) в файле.

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

ls затем выводит сообщения об ошибках на стандартный вывод, и они сохраняются в файле, начиная с самого начала. Мы все еще в порядке; файл выглядит так:

ls: cannot access 'file2.txt': No such file or directory
ls: cannot access 'file3.txt': No such file or directory

После этого ls начинает записывать найденные файлы в стандартный вывод. И здесь возникает проблема: дескриптор файла stdout все еще указывает на начало файла, поэтому он начинает перезаписывать файл с самого начала. Он записывает первое имя файла, давая:

file1.txtt access 'file2.txt': No such file or directory
ls: cannot access 'file3.txt': No such file or directory

Затем он записывает новую строку, которая заменяет "t" на "невозможно", давая:

file1.txt
 access 'file2.txt': No such file or directory
ls: cannot access 'file3.txt': No such file or directory

Затем он записывает следующий имя файла, что дает:

file1.txt
file4.txtfile2.txt': No such file or directory
ls: cannot access 'file3.txt': No such file or directory

И затем последний символ новой строки, на этот раз над «f» в «file2»:

file1.txt
file4.txt
ile2.txt': No such file or directory
ls: cannot access 'file3.txt': No such file or directory

... и это конечный результат, который вы видите .

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

0 голосов
/ 05 августа 2020

Почему результаты cmd 2 и cmd 3 разные?

Потому что оба stdout и stderr переопределяют res.txt content

Почему получен cmd 3 правильный вывод даже без использования символа >>, но не cmd 2?

cmd 3 не всегда будет работать, см. " Как перенаправить и добавить stdout и stderr в файл с Bash?"

 ls file{1..4}.txt >>res.txt 2>&1

Это будет работать лучше, потому что файл открывается в режиме добавления, и дескриптор файла '2' для stderr будет использовать тот же режим.

0 голосов
/ 05 августа 2020

В cmd 3 вы перенаправляете stderr на res.txt. Вы найдете сообщение об ошибке в res.txt.

...