Некоторые хитрости о перенаправлении
Некоторые особенности синтаксиса могут иметь важные особенности. Существует несколько маленьких образцов около перенаправлений STDERR
, STDOUT
и аргументы упорядоченности .
1 - перезаписать или добавить?
Символ >
означает перенаправление .
>
означает отправку в виде всего завершенного файла с перезаписью цели, если она существует (см. noclobber
функцию bash на # 3 позже).
>>
означает отправить в дополнение к добавлению к цели, если существует.
В любом случае файл будет создан, если они не существуют.
2 - командная строка оболочки зависит от порядка !!
Для проверки нам нужна простая команда, которая отправит что-то на оба вывода :
$ ls -ld /tmp /tnt
ls: cannot access /tnt: No such file or directory
drwxrwxrwt 118 root root 196608 Jan 7 11:49 /tmp
$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory
$ ls -ld /tmp /tnt 2>/dev/null
drwxrwxrwt 118 root root 196608 Jan 7 11:49 /tmp
(Ожидая, что у вас нет каталога с именем /tnt
, конечно;). Ну, у нас это есть !!
Итак, давайте посмотрим:
$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory
$ ls -ld /tmp /tnt >/dev/null 2>&1
$ ls -ld /tmp /tnt 2>&1 >/dev/null
ls: cannot access /tnt: No such file or directory
Последняя командная строка выводит данные STDERR
на консоль, и это, кажется, не ожидаемое поведение ... Но ...
Если вы хотите сделать некоторую пост-фильтрацию для одного выхода, другого или обоих:
$ ls -ld /tmp /tnt | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory
<-- drwxrwxrwt 118 root root 196608 Jan 7 12:02 /tmp --->
$ ls -ld /tmp /tnt 2>&1 | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->
<-- drwxrwxrwt 118 root root 196608 Jan 7 12:02 /tmp --->
$ ls -ld /tmp /tnt >/dev/null | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory
$ ls -ld /tmp /tnt >/dev/null 2>&1 | sed 's/^.*$/<-- & --->/'
$ ls -ld /tmp /tnt 2>&1 >/dev/null | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->
Обратите внимание, что последняя командная строка в этом абзаце точно такая же, как и в предыдущем абзаце, где я написал , что это не ожидаемое поведение (так что это может быть даже ожидаемое поведение).
Ну, есть несколько хитростей по поводу перенаправлений для
выполнения разных операций на обоих выходах :
$ ( ls -ld /tmp /tnt | sed 's/^/O: /' >&9 ) 9>&2 2>&1 | sed 's/^/E: /'
O: drwxrwxrwt 118 root root 196608 Jan 7 12:13 /tmp
E: ls: cannot access /tnt: No such file or directory
Примечание: &9
дескриптор возникнет самопроизвольно из-за ) 9>&2
.
Приложение: нота! С новой версиейудар( >4.0
) есть новая функция и более привлекательный синтаксис для таких вещей:
$ ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /')
O: drwxrwxrwt 17 root root 28672 Nov 5 23:00 /tmp
E: ls: cannot access /tnt: No such file or directory
И, наконец, для такого каскадного форматирования вывода:
$ ((ls -ld /tmp /tnt |sed 's/^/O: /' >&9 ) 2>&1 |sed 's/^/E: /') 9>&1| cat -n
1 O: drwxrwxrwt 118 root root 196608 Jan 7 12:29 /tmp
2 E: ls: cannot access /tnt: No such file or directory
Приложение: нота! Тот же новый синтаксис, в обоих направлениях:
$ cat -n <(ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /'))
1 O: drwxrwxrwt 17 root root 28672 Nov 5 23:00 /tmp
2 E: ls: cannot access /tnt: No such file or directory
Где STDOUT
проходит определенный фильтр, STDERR
другой и, наконец, оба слитых выхода проходят через третий фильтр команд.
3 - Слово о noclobber
опции и >|
синтаксисе
Это о перезаписи :
В то время как set -o noclobber
команда bash не перезаписывает ни один из существующих файлов, >|
синтаксис позволяет вам преодолеть это ограничение:
$ testfile=$(mktemp /tmp/testNoClobberDate-XXXXXX)
$ date > $testfile ; cat $testfile
Mon Jan 7 13:18:15 CET 2013
$ date > $testfile ; cat $testfile
Mon Jan 7 13:18:19 CET 2013
$ date > $testfile ; cat $testfile
Mon Jan 7 13:18:21 CET 2013
Файл перезаписывается каждый раз, а теперь:
$ set -o noclobber
$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan 7 13:18:21 CET 2013
$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan 7 13:18:21 CET 2013
Пройдите через >|
:
$ date >| $testfile ; cat $testfile
Mon Jan 7 13:18:58 CET 2013
$ date >| $testfile ; cat $testfile
Mon Jan 7 13:19:01 CET 2013
Отключение этой опции и / или запрос, если он уже установлен.
$ set -o | grep noclobber
noclobber on
$ set +o noclobber
$ set -o | grep noclobber
noclobber off
$ date > $testfile ; cat $testfile
Mon Jan 7 13:24:27 CET 2013
$ rm $testfile
4 - Последний трюк и многое другое ...
Для перенаправления обоих выходных данных из данной команды мы видим, что правильный синтаксис может быть:
$ ls -ld /tmp /tnt >/dev/null 2>&1
для этого особого случая есть сокращенный синтаксис: &>
... или>&
$ ls -ld /tmp /tnt &>/dev/null
$ ls -ld /tmp /tnt >&/dev/null
Примечание: если 2>&1
существует, 1>&2
правильный синтаксис тоже:
$ ls -ld /tmp /tnt 2>/dev/null 1>&2
4b- Теперь я дам вам подумать о:
$ ls -ld /tmp /tnt 2>&1 1>&2 | sed -e s/^/++/
++/bin/ls: cannot access /tnt: No such file or directory
++drwxrwxrwt 193 root root 196608 Feb 9 11:08 /tmp/
$ ls -ld /tmp /tnt 1>&2 2>&1 | sed -e s/^/++/
/bin/ls: cannot access /tnt: No such file or directory
drwxrwxrwt 193 root root 196608 Feb 9 11:08 /tmp/
4c- Если вы заинтересованы в дополнительной информации
Вы можете прочитать прекрасное руководство, нажав:
man -Len -Pless\ +/^REDIRECTION bash
в удар приставка ;-)