Деякі хитрощі щодо перенаправлення
Деякі особливості синтаксису щодо цього можуть мати важливу поведінку. Існує кілька маленьких зразків близько перенаправлень 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
.
Додаток: nota! З новою версієюбаш( >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
в баш консоль ;-)