bash
などの一部のシェル 、次のように、プロセス出力をファイルとして表示する方法であるプロセス置換をサポートします。
$ diff <(sort file1) <(sort file2)
ただし、この構成はPOSIXではないため、移植性はありません。 POSIXに適した方法でプロセス置換を実現するにはどうすればよいですか (つまり、/bin/sh
で機能するもの )?
注:質問は、2つのソートされたファイルを比較する方法を尋ねているのではありません。これは、プロセス置換を示すための考案された例にすぎません!
承認された回答:
この機能はksh
によって導入されました (ksh86で最初に文書化されました)そして/dev/fd/n
機能
(以前の一部のBSDおよびAT&Tシステムで個別に追加されました)。
ksh
で ksh93uまでは、システムが/dev/fd/n
。 zsh、bash、およびksh93u+
以上は、/dev/fd/n
利用できません。
/dev/fd/n
が利用可能です(POSIXはそれらを指定していません)。
プロセス置換を実行できます(例: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
を開きます。 ここで、fd3がソケットを指している場合はLinuxでは機能しません。
POSIXは/dev/fd/n
、名前付きパイプを指定します。名前付きパイプは、ファイルシステムからアクセスできることを除けば、通常のパイプと同じように機能します。ここでの問題は、一時的なものを作成して後でクリーンアップする必要があることです。これは、特にPOSIXに標準のメカニズム(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"
cleanup
(ここでは信号処理は行いません)。
関連:ターミナルを開いた直後にプロセスが完了し、コマンドを追加できませんか?