Книга: Искусство программирования на языке сценариев командной оболочки
Глава 16. Перенаправление ввода/вывода
В системе по-умолчанию всегда открыты три "файла" -- stdin (клавиатура), stdout (экран) и stderr (вывод сообщений об ошибках на экран). Эти, и любые другие открытые файлы, могут быть перенапрвлены. В данном случае, термин "перенаправление" означает получить вывод из файла, команды, программы, сценария или даже отдельного блока в сценарии (см. Пример 3-1 и Пример 3-2) и передать его на вход в другой файл, команду, программу или сценарий.
С каждым открытым файлом связан дескриптор файла[ 44 ]. Дескрипторы файлов stdin, stdout и stderr -- 0, 1 и 2, соответственно. При открытии дополнительных файлов, дескрипторы с 3 по 9 остаются незанятыми. Иногда дополнительные дескрипторы могут сослужить неплохую службу, временно сохраняя в себе ссылку на stdin, stdout или stderr[ 45 ]. Это упрощает возврат дескрипторов в нормальное состояние после сложных манипуляций с перенаправлением и перестановками (см. Пример 16-1).
COMMAND_OUTPUT >
# Перенаправление stdout (вывода) в файл.
# Если файл отсутствовал, то он создется, иначе -- перезаписывается.
ls -lR > dir-tree.list
# Создает файл, содержащий список дерева каталогов.
: > filename
# Операция > усекает файл "filename" до нулевой длины.
# Если до выполнения операции файла не существовало,
# то создается новый файл с нулевой длиной (тот же эффект дает команда 'touch').
# Символ : выступает здесь в роли местозаполнителя, не выводя ничего.
> filename
# Операция > усекает файл "filename" до нулевой длины.
# Если до выполнения операции файла не существовало,
# то создается новый файл с нулевой длиной (тот же эффект дает команда 'touch').
# (тот же результат, что и выше -- ": >", но этот вариант неработоспособен
# в некоторых командных оболочках.)
COMMAND_OUTPUT >>
# Перенаправление stdout (вывода) в файл.
# Создает новый файл, если он отсутствовал, иначе -- дописывает в конец файла.
# Однострочные команды перенаправления
# (затрагивают только ту строку, в которой они встречаются):
# --------------------------------------------------------------------
1>filename
# Перенаправление вывода (stdout) в файл "filename".
1>>filename
# Перенаправление вывода (stdout) в файл "filename", файл открывается в режиме добавления.
2>filename
# Перенаправление stderr в файл "filename".
2>>filename
# Перенаправление stderr в файл "filename", файл открывается в режиме добавления.
&>filename
# Перенаправление stdout и stderr в файл "filename".
#==============================================================================
# Перенаправление stdout, только для одной строки.
LOGFILE=script.log
echo "Эта строка будет записана в файл "$LOGFILE"." 1>$LOGFILE
echo "Эта строка будет добавлена в конец файла "$LOGFILE"." 1>>$LOGFILE
echo "Эта строка тоже будет добавлена в конец файла "$LOGFILE"." 1>>$LOGFILE
echo "Эта строка будет выведена на экран и не попадет в файл "$LOGFILE"."
# После каждой строки, сделанное перенаправление автоматически "сбрасывается".
# Перенаправление stderr, только для одной строки.
ERRORFILE=script.errors
bad_command1 2>$ERRORFILE # Сообщение об ошибке запишется в $ERRORFILE.
bad_command2 2>>$ERRORFILE # Сообщение об ошибке добавится в конец $ERRORFILE.
bad_command3 # Сообщение об ошибке будет выведено на stderr,
#+ и не попадет в $ERRORFILE.
# После каждой строки, сделанное перенаправление также автоматически "сбрасывается".
#==============================================================================
2>&1
# Перенаправляется stderr на stdout.
# Сообщения об ошибках передаются туда же, куда и стандартный вывод.
i>&j
# Перенаправляется файл с дескриптором i в j.
# Вывод в файл с дескриптором i передается в файл с дескриптором j.
>&j
# Перенаправляется файл с дескриптором 1 (stdout) в файл с дескриптором j.
# Вывод на stdout передается в файл с дескриптором j.
0< FILENAME
< FILENAME
# Ввод из файла.
# Парная команде ">", часто встречается в комбинации с ней.
#
# grep search-word <filename
[j]<>filename
# Файл "filename" открывается на чтение и запись, и связывается с дескриптором "j".
# Если "filename" отсутствует, то он создается.
# Если дескриптор "j" не указан, то, по-умолчанию, бередся дескриптор 0, stdin.
#
# Как одно из применений этого -- запись в конкретную позицию в файле.
echo 1234567890 > File # Записать строку в файл "File".
exec 3<> File # Открыть "File" и связать с дескриптором 3.
read -n 4 <&3 # Прочитать 4 символа.
echo -n . >&3 # Записать символ точки.
exec 3>&- # Закрыть дескриптор 3.
cat File # ==> 1234.67890
# Произвольный доступ, да и только!
|
# Конвейер (канал).
# Универсальное средство для объединения команд в одну цепочку.
# Похоже на ">", но на самом деле -- более обширная.
# Используется для объединения команд, сценариев, файлов и программ в одну цепочку (конвейер).
cat *.txt | sort | uniq > result-file
# Содержимое всех файлов .txt сортируется, удаляются повторяющиеся строки,
# результат сохраняется в файле "result-file".
Операции перенаправления и/или конвейеры могут комбинироваться в одной командной строке.
command < input-file > output-file
command1 | command2 | command3 > output-file
См. Пример 12-23 и Пример A-17.
Допускается перенаправление нескольких потоков в один файл.
ls -yz >> command.log 2>&1
# Сообщение о неверной опции "yz" в команде "ls" будет записано в файл "command.log".
# Поскольку stderr перенаправлен в файл.
Закрытие дескрипторов файлов
n<&-
Закрыть дескриптор входного файла n.
0<&-, <&-
Закрыть stdin.
n>&-
Закрыть дескриптор выходного файла n.
1>&-, >&-
Закрыть stdout.
Дочерние процессы наследуют дескрипторы открытых файлов. По этой причине и работают конвейеры. Чтобы предотвратить наследование дескрипторов -- закройте их перед запуском дочернего процесса.
# В конвейер передается только stderr.
exec 3>&1 # Сохранить текущее "состояние" stdout.
ls -l 2>&1 >&3 3>&- | grep bad 3>&- # Закрыть дескр. 3 для 'grep' (но не для 'ls').
# ^^^^ ^^^^
exec 3>&- # Теперь закрыть его для оставшейся части сценария.
# Спасибо S.C.
Дополнительные сведения о перенаправлении ввода/вывода вы найдете в Приложение D.
16.1. С помощью команды exec
- 4.11.7. Перенаправление
- Перенаправление портов
- Перенаправление ввода
- Пример: перенаправление ввода
- Приложение D. Подробное введение в операции ввода-вывода и перенаправление ввода-вывода
- 5.4.3. Перенаправление стандартных потоков ввода, вывода и ошибок
- Пример 11-6. Чтение командой read из файла через перенаправление
- 5.2. Перенаправление ввода
- Пример 3-1. Вложенные блоки и перенаправление ввода-вывода
- Перенаправление ввода и вывода
- Глава 16. Перенаправление ввода
- 19.7.2. Перенаправление ввода