Подстановка процессов -- это аналог подстановки команд. Операция подстановки команд записывает в переменную результат выполнения некоторой команды, например, dir_contents=`ls -al` или xref=$(grep word datafile). Операция подстановки процессов передает вывод одного процесса на ввод другого (другими словами, передает результат выполнения одной команды -- другой).
- Внутри круглых скобок
-
>(command)
<(command)
Таким образом инициируется подстановка процессов. Здесь, для передачи результата работы процесса в круглых скобках, используются файлы /dev/fd/<n>. [50]
Между круглой скобкой и символом "<" или ">", не должно быть пробелов, в противном случае это вызовет сообщение об ошибке.
bash$ echo >(true) /dev/fd/63 bash$ echo (true) /dev/fd/63
Bash создает канал с двумя файловыми дескрипторами, --fIn и fOut--. stdin команды true присоединяется к fOut (dup2(fOut, 0)), затем Bash передает /dev/fd/fIn в качестве аргумента команде echo. В системах, где отсутствуют файлы /dev/fd/<n>, Bash может использовать временные файлы. (Спасибо S.C.)
cat (ls -l) # То же самое, что и ls -l | cat sort -k 9 (ls -l /bin) (ls -l /usr/bin) (ls -l /usr/X11R6/bin) # Список файлов в трех основных каталогах 'bin', отсортированный по именам файлов. # Обратите внимание: на вход 'sort' поданы три самостоятельные команды. diff (command1) (command2) # Выдаст различия в выводе команд. tar cf >(bzip2 -c > file.tar.bz2) $directory_name # Вызовет "tar cf /dev/fd/?? $directory_name" и затем "bzip2 -c > file.tar.bz2". # # Из-за особенностей, присущих некоторым системам, связанным с /dev/fd/, # канал между командами не обязательно должен быть именованным. # # Это можно сделать и так. # bzip2 -c pipe > file.tar.bz2& tar cf pipe $directory_name rm pipe # или exec 3>&1 tar cf /dev/fd/4 $directory_name 4>&1 >&3 3>&- | bzip2 -c > file.tar.bz2 3>&- exec 3>&- # Спасибо S.C.
Ниже приводится еще один очень интересный пример использования подстановки процессов.
# Фрагмент сценария из дистрибутива SuSE: while read des what mask iface; do # Некоторые команды ... done (route -n) # Чтобы проверить это, попробуем вставить команду, выполняющую какие либо действия. while read des what mask iface; do echo $des $what $mask $iface done (route -n) # Вывод на экран: # Kernel IP routing table # Destination Gateway Genmask Flags Metric Ref Use Iface # 127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo # Как указывает S.C. -- более простой для понимания эквивалент: route -n | while read des what mask iface; do # Переменные берут значения с устройства вывода конвейера (канала). echo $des $what $mask $iface done # На экран выводится то же самое, что и выше. # Однако, Ulrich Gayer отметил, что ... #+ этот вариант запускает цикл while в подоболочке, #+ и поэтому переменные не видны за пределами цикла, после закрытия канала.
Notes
[50] |
Имеет тот же эффект, что и именованные каналы (временный файл), фактически, именованные каналы некогда использовались в операциях подстановки процессов. |