该功能由ksh
(首次在ksh86中记录)引入,并利用了该/dev/fd/n
功能(先前在某些BSD和AT&T系统中独立添加)。在ksh
ksh93u及更高版本中,除非您的系统支持/ dev / fd / n,否则它将无法正常工作。zsh,bash及ksh93u+
更高版本可以使用临时命名管道(我相信SysIII中添加了命名管道),其中/ dev / fd / n不可用。
在可用的系统上(POSIX未指定那些系统),您可以使用以下方法自己进行进程替换():/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
但是,这ksh93
在Linux上不起作用,shell管道是用套接字对而不是管道实现的,并且/dev/fd/3
fd 3指向套接字的打开在Linux上不起作用。
尽管POSIX没有指定。它确实指定了命名管道。命名管道的工作方式与普通管道类似,只是您可以从文件系统访问它们。这里的问题是,您必须创建临时文件并随后进行清理,这很难可靠地完成,特别是考虑到POSIX没有标准机制(如某些系统上的标准)来创建临时文件或目录,并且可移植地进行信号处理(挂断或杀死时进行清理)也很难移植。/dev/fd/n
mktemp -d
您可以执行以下操作:
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"
(此处不处理信号处理)。