4. Перенаправления и каналы

4.1. Немного подробнее о процессах

Чтобы понять принцип действия перенаправлений и каналов, мы должны объяснить понятие процесса, которое пока еще не было представлено. Большинство процессов UNIX® (сюда также включаются графические приложения, но исключается большинство демонов) использует как минимум три файловых дескриптора: стандартный ввод, стандартный вывод и стандартный поток ошибок. Их соответствующие номера - 0, 1 и 2. В общем случае эти три дескриптора ассоциируются с терминалом, из которого был запущен процесс, с клавиатурой в качестве устройства ввода. Цель перенаправлений и каналов - переадресация этих дескрипторов. Примеры в этом разделе помогут вам лучше понять этот принцип.

4.2. Перенаправления

Допустим вам надо получить список файлов, имена которых заканчиваются на .png [15] в каталоге images. Этот список очень длинный, поэтому у вас может возникнуть желание сохранить его в файл для того, чтобы просмотреть его позже. Вы можете ввести следующую команду:

$ ls images/*.png 1>file_list

Это означает, что стандартный вывод этой команды (1) перенаправляется (>) в файл с именем file_list. Оператор > - это оператор перенаправления вывода. Если файл для перенаправления не существует, он будет создан, но если он существует, его предыдущее содержимое будет перезаписано. Однако дескриптором по умолчанию, который перенаправляется этим оператором, является стандартный вывод, и поэтому нет необходимости явным образом указывать его в командной строке. Следовательно, вы можете записать команду более упрощенно:

$ ls images/*.png >file_list

и результат при этом будет точно таким же. Затем вы можете просмотреть файл при помощи программы просмотра текстовых файлов, например, less.

Теперь представьте, что вам нужно узнать, сколько существует этих файлов. Вместо того, чтобы считать их вручную, вы можете воспользоваться утилитой под названием wc (Word Count - подсчет слов) с опцией -l, которая выводит на стандартный вывод число строк в файле. Вот один из вариантов решения:

$ wc -l 0<file_list

который выдаст вам искомый результат. Оператор < - это оператор перенаправления ввода, а дескриптором по умолчанию, который перенаправляется этим оператором, является стандартный ввод, т.е. 0, и вы можете ввести просто строку:

$ wc -l <file_list

Теперь представьте, что вам нужно удалить все «расширения» файлов и поместить результат в другой файл. Одной из утилит для выполнения этого является sed (Stream EDitor - потоковый редактор). Вы просто перенаправляете стандартный ввод sed в файл file_list, а его вывод перенаправляете в результирующий файл, т.е. the_list:

$ sed -e 's/\.png$//g' <file_list >the_list

и ваш список создан, готовый для просмотра в удобное для вас время любой из программ просмотра.

Также полезным может оказаться перенаправлять стандартный поток ошибок.Например, вам нужно узнать, к каким каталогам в /shared у вас нет доступа: одним из решений будет рекурсивное получение списка файлов в этом каталоге и перенаправление ошибок в файл, не показывая при этом стандартного вывода:

$ ls -R /shared >/dev/null 2>errors

это означает, что стандартный вывод будет перенаправлен (>) в специальный файл /dev/null, в котором удаляется все, что вы в него записываете (т.е. стандартный вывод не отображается), а стандартный поток ошибок (2) перенаправляется (>) в файл errors.

4.3. Каналы

Каналы (pipes) - это, в некотором роде, комбинирование перенаправлений ввода и вывода. Принцип действия подобен физическому каналу, отсюда и такое название: один процесс отправляет данные в один конец канала, а другой процесс считывает данные на другом конце. Оператор канала - |. Давайте вернемся назад к примеру со списком файлов. Допустим, вам нужно сразу узнать, сколько там соответствующих файлов, но без сохранения списка во временном файле. Тогда вам надо воспользоваться следующей командой:

$ ls images/*.png | wc -l

которая означает, что стандартный вывод команды ls (т.е. список файлов) перенаправляется на стандартный ввод команды wc. При этом вы получите искомый результат.

Также вы можете сразу составить список файлов «без расширений», воспользовавшись следующей командой:

$ ls images/*.png | sed -e 's/\.png$//g' >the_list

или же, если вы хотите увидеть список сразу, не сохраняя его в файл:

$ ls images/*.png | sed -e 's/\.png$//g' | less

Действие каналов и перенаправлений не ограничивается только текстом, который может читать человек. Например, следующая команда, выполненная в Терминал'е:

$ xwd -root | convert - ~/my_desktop.png

отправит снимок вашего рабочего стола в файл my_desktop.png [16] в вашем личном каталоге.



[15] Вы могли подумать, что глупо говорить «файлы, оканчивающиеся на .png», а не просто «PNG-изображения». Однако, следует напомнить, что в UNIX® понятие расширения принято условно: расширения вовсе не обязаны определять типы файлов. Файл, оканчивающийся на .png, с тем же успехом может быть изображением JPEG, файлом приложения, текстовым файлом или файлом любого другого типа. Кстати, то же самое справедливо и для Windows®!

[16] Да, это и в самом деле будет изображение PNG (однако должен быть установлен пакет ImageMagick).