Esse recurso foi introduzido por ksh
(em ksh86) e estava fazendo uso do recurso /dev/fd/n
(adicionado independentemente em alguns sistemas BSDs e AT & T anteriormente). Em ksh
e até ksh93u, não funcionaria a menos que seu sistema tivesse suporte para / dev / fd / n. zsh, bash e ksh93u+
e acima podem fazer uso de pipes nomeados temporários (pipes nomeados adicionados em SysIII eu acredito) onde / dev / fd / n não estão disponíveis.
Nos sistemas em que /dev/fd/n
está disponível (o POSIX não especifica esses), você mesmo pode fazer a substituição do processo ( diff <(cmd1) <(cmd2)
) com:
{
cmd1 4<&- | {
# in here fd 3 points to the reading end of the pipe
# from cmd1, while fd 0 has been restored from the original
# stdin (saved on fd 4, now closed as no longer needed)
cmd2 3<&- | diff /dev/fd/3 -
} 3<&0 <&4 4<&- # restore the original stdin for cmd2
} 4<&0 # save a copy of stdin for cmd2
No entanto, como isso não funciona com ksh93
no Linux, os shell pipes são implementados com socketpairs em vez de pipes e abrindo /dev/fd/3
, onde fd3 aponta para um soquete que não funciona no Linux.
Embora o POSIX não especifique /dev/fd/n
. Ele especifica pipes nomeados. Os pipes nomeados funcionam como pipes normais, exceto que você pode acessá-los a partir do sistema de arquivos. A questão aqui é que você tem que criar temporários e limpar depois, o que é difícil de fazer de forma confiável, especialmente considerando que POSIX não tem mecanismo padrão (como mktemp -d
como encontrado em alguns sistemas) para criar arquivos ou diretórios temporários, e fazer o manuseio de sinal de forma portável (para limpeza após desligamento ou interrupção) também é difícil de ser feito de forma portável.
Você pode fazer algo como:
tmpfifo() (
n=0
until
fifo=$1.$$.$n
mkfifo -m 600 -- "$fifo" 2> /dev/null
do
n=$((n + 1))
# give up after 20 attempts as it could be a permanent condition
# that prevents us from creating fifos. You'd need to raise that
# limit if you intend to create (and use at the same time)
# more than 20 fifos in your script
[ "$n" -lt 20 ] || exit 1
done
printf '%s\n' "$fifo"
)
cleanup() { rm -f -- "$fifo"; }
fifo=$(tmpfifo /tmp/fifo) || exit
cmd2 > "$fifo" & cmd1 | diff - "$fifo"
rm -f -- "$fifo"
(não está cuidando do manuseio de sinal aqui).