コンピュータにおいて、プロセス置換とは、コマンドの入力または出力をファイルパスとして利用可能にするプロセス間通信の一形態です。コマンドシェルは、通常ファイル名が記述される場所に、コマンドをインラインで置換します。これにより、通常はファイルパスしか受け付けないプログラムでも、別のプログラムから直接読み書きできるようになります。
プロセス置換は、ベル研究所のKornShellによって初めて導入され、 1986年に初めて文書化されました[ 1 ]。当初は文字デバイスファイルをサポートするシステムでのみ利用可能でした。rcシェルは、1990年にリリースされたUnixバージョン10で、異なる構文で「パイプライン分岐」としてこの機能を提供しています[ 2 ]。Zシェルは、1990年にリリースされた最初のバージョン1.0からこの機能を備えており[ 3 ]、Bashシェルは、1993年にリリースされたバージョン1.13.4からこの機能を備えており[ 4 ] 、どちらもKorn Shell構文を使用しています。ksh86/dev/fd/n
=(cmd)Zsh(1990年の最初のバージョン以来)は、パイプの代わりに一時ファイルを使用する第3のプロセス置換()を追加しました。fishシェルは、2005年にパイプを使用する別の構文で独自のプロセス置換を追加し、その後2007年に一時ファイルを使用するバリアントを追加しました。パイプバリアントはデッドロックに悩まされていたため、これが(最初は意図せず)デフォルトになりました[ 5 ]。
以下の例では、KornShell構文を使用しています。
Unixのdiffコマンドは通常、比較する2つのファイル名、または1つのファイル名と標準入力を受け付けます。プロセス置換を使用すると、2つのプログラムの出力を直接比較できます。
$ diff < ( sort file1 ) < ( sort file2 )この<(command)式は、コマンドインタープリタに対し、指定されたコマンドを実行し、その出力をファイルとして表示するように指示します。このコマンドは、任意の複雑なシェルコードを指定できます。
工程代替を行わない場合、代替案は以下のとおりです。
$ sort file2 > file2.sorted $ sort file1 | diff - file2.sorted $ rm file2.sorted $ mkfifo sort2.fifo $ sort file2 > sort2.fifo & $ sort file1 | diff - sort2.fifo $ rm /tmp/sort2.fifo /dev/fd/n$ sort file1 | { sort file2 3 < & - | diff /dev/fd/3 - ; } 3 < & 0それらはすべて、より面倒な作業となる。
プロセス置換を使用すると、通常はファイルに書き込まれる出力をキャプチャして、プロセスの入力にリダイレクトすることもできます。プロセスに書き込むための KornShell 構文は です。以下は、 、およびコマンドを使用して、 でファイルの行数をカウントし、 で圧縮する>(command)例です。teewcgzipwc -lgzip
$ tee > ( wc -l > & 2 ) < bigfile | gzip > bigfile.gz 工程代替法が他の代替法に比べて持つ主な利点は以下のとおりです。
内部的には、コマンドが並行して実行されるプロセス置換のバリアントには、2 つの実装方法があります。 をサポートするシステム/dev/fd(ほとんどの Unix 系システム) では、ほとんどの実装は、新しい匿名パイプのファイルディスクリプタを返すpipe()システムコールを呼び出し、文字列 を作成して、それをコマンドラインで置換することによって機能します。サポートしないシステムでは、新しい一時ファイル名を指定して を呼び出し、名前付きパイプを作成し、このファイル名をコマンドラインで置換します。関連する手順を説明するために、 をサポートするシステムでの次の単純なコマンド置換を考えてみましょう。$fd/dev/fd/$fd/dev/fdmkfifo()/dev/fd
$ diff file1 < ( sort file2 )シェルが実行する手順は次のとおりです。
/dev/fd/63。 のようなコマンドで確認できますecho <(true)。sort file2この場合は)、その出力を匿名パイプにパイプします。diff file1 /dev/fd/63。名前付きパイプの場合、実行方法はパイプの作成と削除のみで異なります。パイプはmkfifo()(新しい一時ファイル名が付けられる)で作成され、で削除されますunlink()。その他の点はすべて同じです。
cmd1 =(cmd2)ZshやFishなどの一時ファイルを使用するバリアントは、cmd1 (cmd2|psub -f)最初にcmd2その出力を一時ファイルにリダイレクトして実行し、次にその一時ファイルのパスに置き換えcmd1て実行し、終了後にそのファイルを自動的に削除します。=(cmd2)cmd1
一時ファイルを使用するバリアントを除き、作成された「ファイル」はシーク可能でもmmap可能でもないため、ファイルへの読み書きを行うプロセスはランダム アクセスを実行できず、最初から最後まで一度読み書きする必要があります。ファイルを開く前に明示的にファイルの種類をチェックするプログラムは、プロセス置換によって生成される「ファイル」が通常のファイルではないため、プロセス置換での動作を拒否する可能性があります。さらに、KornShell、Bash バージョン 4.4 (2016) より前、および Zsh バージョン 5.6 (2018) より前では、プロセス置換を作成したシェルからプロセス置換コマンドの終了ステータスを取得することはできません。 [ 6 ]