Некоторые хитрости о перенаправлении
Некоторые особенности синтаксиса могут иметь важные особенности. Есть несколько небольших примеров о перенаправлениях STDERR
, STDOUT
и аргументах ordering .
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
.
Приложение: nota! С новой версией bash (>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
Приложение: nota! Тот же новый синтаксис, обоими способами:
$ 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
в консоли bash ; -)