<< Предыдущий раздел | /\ Содержание | >> Следующий раздел
Представим себе ситуацию: хочется посмотреть листинг директории /bin (в которой лежат многие программы). Выполняем команду "ls -l /bin" и... Результат в экран не помещается. А ведь бывают директории еще большего объема. Что делать?
Большинство команд выводят информацию на терминал, а некоторые (например, текстовый редактор) вводят данные с терминала. В Unix есть почти универсальное правило: терминал может быть заменен для ввода, вывода или и того, и другого, на файл.
Так, чтобы сохранить вывод нашей команды в файл, надо написать:
bobby:~% ls -l /bin >filelist bobby:~% |
При этом весь вывод команды ls будет вместо терминала отправлен в файл. Символ ">" означает, что выходной поток должен быть помещен в указанный далее файл, а не выведен на терминал. Если в файле что-то было, то старое содержимое будет стерто.
Получив таким образом список файлов, его можно просмотреть командой less.
Еще один пример: можно слить содержимое нескольких файлов в один файл, "перехватив" выходной поток команды cat и отправив его в файл:
bobby:~% cat file1 file2 file3 >all bobby:~% _ |
Сделать то же самое при помощи команды cp нельзя:
bobby:~% cp file1 file2 file3 all cp: copying multiple files, but last argument (all) is not a directory Try `cp --help' for more information. bobby:~% _ |
Символ ">>" действует подобно ">", но указывает на необходимость добавить выходной поток к концу файла, вместо того, чтобы стереть старое содержимое. Например:
bobby:~% cat file1 >all bobby:~% cat file2 file3 >>all bobby:~% _ |
Первая команда cat скопирует содержимое file1 в all, а вторая -- допишет к нему содержимое file2 и file3.
Использование ">>" очень удобно, если есть некий "долгоживущий" файл (например, протокол каких-то действий или результатов), к которому иногда надо дописывать данные в конец. Просто указать ">>" с какой-нибудь командой обычно намного быстрее, чем загружать файл в текстовый редактор и что-то дописывать.
Теперь вернемся к нашему первому примеру: как посмотреть листинг большой директории. Мы отправили вывод команды ls в файл, а потом запустили less для его просмотра. Сам же временный файл не имеет никакого смысла -- потом он больше не нужен.
Можно обойтись без временного файла, воспользовавшись конвейером:
bobby:~% ls -l /bin | less |
Символ "|" означает, что надо взять выходной поток от первой команды, и отправить его на входной поток второй.
Большинство команд, выдающих информацию из файла на экран (cat, more, less) устроены так, что они будут читать входной поток, если не указан никакой файл -- вот почему less показывает то, что ему "пришло" от ls.
|
В отличие от Dos, где тоже поддерживаются операторы перенаправления ввода/вывода, в Unix команды в конвейере запускаются одновременно, и данные передаются через программный канал (это специальное средство, предоставляемое ядром Unix) сразу от одной программы к другой, а не через скрытый временный файл. |
Можно заставить команду читать вместо терминала не только выходной поток другой команды, но и обычный файл. Это делается при помощи оператора "<", который указывает, что вместо терминала надо брать входной поток из указанного далее файла. Пример (команда "sort" построчно сортирует входные данные):
bobby:~% cat proverbs What is worth doing, is worth doing well. Art is long, life is short. History repeats itself. Dead men tell no tales. _______________________ bobby:~% sort <proverbs Art is long, life is short. Dead men tell no tales. History repeats itself. What is worth doing, is worth doing well. _______________________ bobby:~% _ |
Что будет, если мы попросим ls показать файлы, которых нет?
bobby:~% ls -l file1 file2 file10 file11 /bin/ls: file10: No such file or directory /bin/ls: file11: No such file or directory -rw-r--r-- 1 ivanov lab5 76 Feb 21 13:23 file1 -rw-r--r-- 1 ivanov lab5 32 Feb 21 13:23 file2 bobby:~% _ |
Файлы которые есть, ls покажет, а про остальные скажет, что их нет. А теперь перенаправим вывод ls в файл:
bobby:~% ls -l file1 file2 file10 file11 >filelist /bin/ls: file10: No such file or directory /bin/ls: file11: No such file or directory bobby:~% _ |
В чем же дело?! Казалось бы, на экране ничего не должно появиться...
А дело в том, что кроме выходного потока есть еще поток сообщений об ошибках, и "культурно" написанные программы все "ругательства" отправляют туда. Чтобы перенаправить в файл поток сообщений об ошибках (обычно его сокращенно называют stderr), надо перед символом ">" указать номер потока -- 2. Пример:
bobby:~% ls -l file1 file2 file10 file11 >filelist 2>errs bobby:~% cat filelist -rw-r--r-- 1 ivanov lab5 76 Feb 21 13:23 file1 -rw-r--r-- 1 ivanov lab5 32 Feb 21 13:23 file2 bobby:~% cat errs /bin/ls: file10: No such file or directory /bin/ls: file11: No such file or directory bobby:~% _ |
|
Такое перенаправление потока stderr невозможно в оболочках csh и tcsh -- в них для этого используется другой, более запутанный синтаксис. |
|
Те, кто программировал на языке C, знают, что там есть три стандартных файловых потока для ввода/вывода: stdin (входной поток, дескриптор 0), stdout (выходной поток, дескриптор 1) и stderr (поток сообщений об ошибках, дескриптор 2). Операторы ">", "<" и "2>" перенаправляют именно эти потоки. |
С потоком stderr обычно требуется сделать одну из трех вещей: перенаправить его туда же, куда и выходной поток, направить в отдельный файл, или отправить "в никуда". В первом случае можно воспользоваться специальной формой оператора перенаправления вывода -- "2>&1" ("отправь второй поток (stderr) туда же, куда и первый (stdout)):
bobby:~% ls -l file1 file2 file10 file11 >filelist 2>&1 bobby:~% cat filelist /bin/ls: file10: No such file or directory /bin/ls: file11: No such file or directory -rw-r--r-- 1 ivanov lab5 76 Feb 21 13:23 file1 -rw-r--r-- 1 ivanov lab5 32 Feb 21 13:23 file2 bobby:~% _ |
Этот способ работает и тогда, когда стандартный вывод отправляется по конвейеру другой программе.
Во третьем же случае надо отправить stderr в "черную дыру" -- файл /dev/null:
bobby:~% ls -l file1 file2 file10 file11 >filelist 2>/dev/null bobby:~% cat filelist -rw-r--r-- 1 ivanov lab5 76 Feb 21 13:23 file1 -rw-r--r-- 1 ivanov lab5 32 Feb 21 13:23 file2 bobby:~% _ |
Подробную информацию на эту тему можно найти в info-документации на zsh, набрав команду "info zsh redirection".
Здесь же следует лишь заметить, что zsh обладает способностью перенаправлять вывод в несколько файлов сразу. Это бывает полезно, если хочется запустить какую-нибудь "долгоиграющую" команду так, чтобы ее вывод сохранялся в файле, но при этом отображался бы и на экране -- для этого надо перенаправить вывод одновременно в файл "протокола" и в файл /dev/tty.
<< Предыдущий раздел | /\ Содержание | >> Следующий раздел