Эта функция была введена ksh
(впервые задокументирована в ksh86) и использовала эту /dev/fd/n
функцию (добавлена независимо в некоторых BSD и системах AT & T ранее). В ksh
и до ksh93u, он не будет работать , если ваша система не имеет поддержки / DEV / FD / н. 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, так как там, каналы оболочки реализованы с парами сокетов вместо каналов и открытием, /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"
(не заботясь об обработке сигналов здесь).