Você pode reproduzir o que a casca faz sob o capô, fazendo o encanamento manualmente. Se o seu sistema tiver /dev/fd/NNN
entradas, você pode usar o embaralhamento do descritor de arquivo: você pode traduzir
main_command <(produce_arg1) <(produce_arg2) >(consume_arg3) >(consume_arg4)
para
{ produce_arg1 |
{ produce_arg2 |
{ main_command /dev/fd5 /dev/fd6 /dev/fd3 /dev/fd4 </dev/fd/8 >/dev/fd/9; } 5<&0 3>&1 |
consume_arg3; } 6<&0 4>&1; |
consume_arg4; } 8<&0 9>&1
Eu mostrei um exemplo mais complexo para ilustrar várias entradas e saídas. Se você não precisa ler a entrada padrão, e a única razão pela qual você está usando a substituição do processo é que o comando requer um nome de arquivo explícito, você pode simplesmente usar /dev/stdin
:
main_command <(produce_arg1)
produce_arg1 | main_command /dev/stdin
Sem /dev/fd/NNN
, você precisa usar um canal nomeado . Um pipe nomeado é uma entrada de diretório, então você precisa criar um arquivo temporário em algum lugar, mas esse arquivo é apenas um nome, ele não contém nenhum dado.
tmp=$(mktemp -d)
mkfifo "$tmp/f1" "$tmp/f2" "$tmp/f3" "$tmp/f4"
produce_arg1 >"$tmp/f1" &
produce_arg2 >"$tmp/f2" &
consume_arg3 <"$tmp/f3" &
consume_arg4 <"$tmp/f4" &
main_command "$tmp/f1" "$tmp/f2" "$tmp/f3" "$tmp/f4"
rm -r "$tmp"