Esse recurso foi introduzido por ksh
(documentado pela primeira vez no ksh86) e estava usando o /dev/fd/n
recurso (adicionado de forma independente em alguns sistemas BSDs e AT&T anteriormente). No ksh
e até o ksh93u, ele não funcionaria, a menos que seu sistema tivesse suporte para / dev / fd / n. zsh, bash e ksh93u+
acima podem fazer uso de pipes nomeados temporários (pipes nomeados adicionados ao SysIII, acredito), onde / dev / fd / n não estão disponíveis.
Nos sistemas em que está disponível (o POSIX não os especifica), você pode fazer a substituição do processo por conta própria ( ) com:/dev/fd/n
diff <(cmd1) <(cmd2)
{
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, isso não funciona ksh93
no Linux, pois os shell pipes são implementados com socketpairs em vez de pipes e a abertura /dev/fd/3
onde fd 3 aponta para um soquete não funciona no Linux.
Embora o POSIX não especifique . Ele especifica pipes nomeados. Os pipes nomeados funcionam como os pipes normais, exceto que você pode acessá-los no sistema de arquivos. O problema aqui é que você precisa criar arquivos temporários e limpar depois, o que é difícil de ser feito com segurança, especialmente considerando que o POSIX não possui mecanismo padrão (como o encontrado em alguns sistemas) para criar arquivos ou diretórios temporários e manipular sinais de maneira portável (limpar após desligar ou matar) também é difícil de executar de forma portável./dev/fd/n
mktemp -d
Você poderia 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 cuidando da manipulação do sinal aqui).