Некоторые хитрости с перенаправлением
Некоторые особенности синтаксиса могут иметь важные особенности. Вот несколько примеров переадресации, 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
.
Дополнение: примечание! В новой версии 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
Дополнение: примечание! Одинаковый новый синтаксис в обоих направлениях:
$ 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 ;-)
person
F. Hauri
schedule
29.04.2013
2>&1
, чем 2 ›/ dev / null ;-) - person F. Hauri   schedule 08.12.2013|&
- это сокращение от2>&1 |
, если вы используете zsh. Я не могу сказать, относится ли это к другим оболочкам, подобным Bourne, или это только функция zsh. - person chrixian   schedule 17.12.2013|&
также есть в Bash, отличная функция. Не POSIX кажется, хотя (?) - person Ciro Santilli 新疆再教育营六四事件ۍ   schedule 27.07.2015