linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Уроки
  • How it works
  • Симулятор
  • База знаний
  • Собеседование
Index
Categories
All entries
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
home/linux/kb/Процессы и ресурсы/process-substitution

kb/processes ── Процессы и ресурсы ── intermediate

Process substitution: <(cmd) и >(cmd)

Bash-синтаксис `<(cmd)` подставляет команду как «псевдо-файл» на чтение. `>(cmd)` - на запись. Получаешь временный файл которого не нужно убирать.

view as markdownaka: proc-sub, process-redirection, anonymous-fifo

Зачем

Часто команда хочет файл на вход, а у тебя есть команда которая выводит данные. Классический пример: diff сравнивает два файла, а ты хочешь сравнить вывод двух команд.

Без process substitution - приходится писать во временные файлы:

bash
ls /etc | sort > /tmp/a.txt
ls /usr | sort > /tmp/b.txt
diff /tmp/a.txt /tmp/b.txt
rm /tmp/a.txt /tmp/b.txt    # не забыть убрать

С process substitution - одна строка:

bash
diff <(ls /etc | sort) <(ls /usr | sort)

Как это работает

<(cmd) под капотом - это /dev/fd/N (где N - какой-то FD, обычно 63 и далее). Bash:

  1. Запускает cmd в подпроцессе
  2. Создаёт пайп
  3. Подставляет в командную строку путь /dev/fd/63 который читает с этого пайпа

Команда (diff) открывает этот «файл» как обычный путь - и читает вывод подпроцесса. Никаких временных файлов на диске не создаётся.

bash
echo <(ls)

▸/dev/fd/63

cat <(echo hello)

▸hello

Симметричный вариант: >(cmd)

>(cmd) - наоборот, псевдо-файл на запись, в который команда читает stream:

bash
echo "data" | tee >(wc -c > /tmp/byte-count.txt) >/dev/null

▸tee пишет копию в подпроцесс wc -c

▸wc -c считает байты и сохраняет в файл

Применение - раздать вывод одной команды в несколько обработчиков параллельно:

bash
some_command | tee >(grep ERROR > errors.log) >(grep WARN > warns.log) > /dev/null

Где НЕ работает

  • POSIX /bin/sh - нет process substitution. Только bash и zsh.
  • Pipe в process substitution - exit-code теряется. Команда внутри <(...) упала, а скрипт этого не заметит даже с set -e. Если важен exit-code - пиши в файл и проверяй явно.
  • Через ssh - ssh host '<(cmd)' не сработает потому что выполняется на удалённой стороне которая может не быть bash.

Идиомы которые точно встретятся

bash
# Сравнить два каталога по содержимому
diff <(ls -la /etc) <(ls -la /etc.bak)
# Проверить что вывод команды совпадает с файлом
diff <(my_program) expected.txt && echo OK
# Записать STDOUT и STDERR в РАЗНЫЕ файлы (без 2>&1)
cmd > >(tee out.log) 2> >(tee err.log >&2)
# Использовать while read с подсчётом совпадений (НЕ через pipe - иначе
# переменная теряется в subshell)
count=0
while read -r line; do
    ((count++))
done < <(grep ERROR app.log)
echo "$count"     # ← переменная сохранилась, потому что НЕТ pipe

Последний случай - частая ловушка: grep ... | while read; do ((count++)); done не работает (count останется 0), потому что pipe запускает while в subshell. Process substitution это лечит.

§ команды

bash
diff <(cmd1) <(cmd2)

Сравнить вывод двух команд без временных файлов

bash
while read x; do ...; done < <(cmd)

Цикл по строкам команды без потери переменных в subshell

bash
tee >(grep err > errors) >(grep warn > warns) > /dev/null

Параллельный fan-out одного потока в несколько обработчиков

bash
comm -12 <(sort a) <(sort b)

Найти строки общие для двух команд (intersection)

§ см. также

  • file-descriptorsFile descriptors (stdin, stdout, stderr)File descriptor - целое число, через которое процесс обращается к открытому файлу/сокету/pipe. У каждого процесса 0/1/2 = stdin/stdout/stderr.
  • heredocHere-doc и here-string: данные внутри скриптаHere-doc (`<<EOF ... EOF`) подаёт многострочный текст на stdin команды без временного файла. Here-string (`<<<`) - то же самое для одной строки.
  • process-and-pidПроцесс и PIDПроцесс - это запущенная программа со своим PID, памятью, открытыми дескрипторами и UID. Все процессы образуют дерево, корень - init (PID 1).

§ упоминается в уроках

  • ›intermediate-11-advanced-redirects
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки