回答:
それらの違いを理解する良い方法は、コマンドラインで少し実験することです。<
キャラクターの使用における視覚的な類似性にもかかわらず、リダイレクトやパイプとは非常に異なることを行います。
date
コマンドをテストに使用してみましょう。
$ date | cat
Thu Jul 21 12:39:18 EEST 2011
これは無意味な例ですが、STDIN cat
の出力を受け入れ、date
それを吐き出すことを示しています。プロセス置換によっても同じ結果が得られます。
$ cat <(date)
Thu Jul 21 12:40:53 EEST 2011
しかし、舞台裏で起こったことは異なっていました。STDINストリームが与えられる代わりに、cat
実際に開いて読み取るために必要なファイルの名前が渡されました。のecho
代わりにを使用すると、この手順を確認できますcat
。
$ echo <(date)
/proc/self/fd/11
catはファイル名を受け取ると、ファイルの内容を読み取ります。一方、echoは渡されたファイルの名前を示しただけです。置換をさらに追加すると、この違いがより明確になります。
$ cat <(date) <(date) <(date)
Thu Jul 21 12:44:45 EEST 2011
Thu Jul 21 12:44:45 EEST 2011
Thu Jul 21 12:44:45 EEST 2011
$ echo <(date) <(date) <(date)
/proc/self/fd/11 /proc/self/fd/12 /proc/self/fd/13
プロセス置換(ファイルを生成する)と入力リダイレクト(ファイルをSTDINに接続する)を組み合わせることができます。
$ cat < <(date)
Thu Jul 21 12:46:22 EEST 2011
ほぼ同じように見えますが、今回はファイル名ではなくSTDINストリームがcatに渡されました。これは、echoで試してみるとわかります。
$ echo < <(date)
<blank>
echoはSTDINを読み取らず、引数が渡されなかったため、何も取得しません。
パイプと入力リダイレクトは、コンテンツをSTDINストリームに押し込みます。プロセス置換はコマンドを実行し、その出力を特別な一時ファイルに保存してから、コマンドの代わりにそのファイル名を渡します。使用しているコマンドは、ファイル名として扱われます。作成されるファイルは通常のファイルではなく、不要になったら自動的に削除される名前付きパイプであることに注意してください。
[[ -p <(date) ]] && echo true
。これはtrue
、bash 4.4または3.2で実行すると生成されます。
bash
posixシェルにはプロセス置換がないので、あなたが話しているのか、他の高度なシェルであると思います。
bash
マニュアルページレポート:
プロセスの置換
プロセスの置換は、名前付きパイプ(FIFO)または開いているファイルに名前を付ける/ dev / fdメソッドをサポートするシステムでサポートされています。<(list)または>(list)の形式を取ります。プロセスリストは、入力または出力がFIFOまたは/ dev / fd内のファイルに接続されて実行されます。このファイルの名前は、展開の結果として現在のコマンドに引数として渡されます。>(list)フォームが使用されている場合、ファイルへの書き込みはリストへの入力を提供します。<(list)形式を使用する場合、引数として渡されたファイルを読み取ってlistの出力を取得する必要があります。
使用可能な場合、プロセス置換は、パラメーターおよび変数の展開、コマンドの置換、および算術展開と同時に実行されます。
つまり、実用的な観点から、次のような式を使用できます
<(commands)
パラメータとしてファイルを必要とする他のコマンドのファイル名として。または、このようなファイルにリダイレクトを使用できます。
while read line; do something; done < <(commands)
あなたの質問に戻ると、プロセスの置換とパイプはあまり共通していないように思えます。
複数のコマンドの出力を順番にパイプする場合は、次のいずれかの形式を使用できます。
(command1; command2) | command3
{ command1; command2; } | command3
ただし、プロセス置換でリダイレクトを使用することもできます
command3 < <(command1; command2)
最後に、command3
ファイルパラメータを受け入れる場合(stdinの代わりに)
command3 <(command1; command2)
ここでは、他の方法では不可能なプロセス置換を使用して実行できる3つのことを示します。
diff <(cd /foo/bar/; ls) <(cd /foo/baz; ls)
パイプでこれを行う方法はありません。
次のものがあるとします。
curl -o - http://example.com/script.sh
#/bin/bash
read LINE
echo "You said ${LINE}!"
そして、あなたはそれを直接実行したい。以下は惨めに失敗します。Bashはすでにスクリプトの読み取りにSTDINを使用しているため、他の入力は不可能です。
curl -o - http://example.com/script.sh | bash
しかし、この方法は完全に機能します。
bash <(curl -o - http://example.com/script.sh)
また、プロセス置換は他の方法でも機能することに注意してください。そのため、次のようなことができます。
(ls /proc/*/exe >/dev/null) 2> >(sed -n \
'/Permission denied/ s/.*\(\/proc.*\):.*/\1/p' > denied.txt )
これは少し複雑な例ですが、stdoutをに送信し/dev/null
、stderrをsedスクリプトにパイプして「Permission denied」エラーが表示されたファイルの名前を抽出し、その結果をファイルに送信します。
最初のコマンドとstdoutリダイレクションは括弧(subshell)で囲まれているため、THATコマンドの結果のみが送信さ/dev/null
れ、残りの行を混乱させないことに注意してください。
diff
例では、cd
失敗する可能性がある場合に注意する必要があることに注意してくださいdiff <(cd /foo/bar/ && ls) <(cd /foo/baz && ls)
。
コマンドがファイルのリストを引数として受け取り、それらのファイルを入力(または出力ですが、一般的ではありません)として処理する場合、これらの各ファイルは、プロセス置換によって透過的に提供される名前付きパイプまたは/ dev / fd疑似ファイルになります:
$ sort -m <(command1) <(command2) <(command3)
sortはコマンドラインで入力ファイルのリストを取得できるため、これにより、ソートする3つのコマンドの出力が「パイプ」されます。
<()
、多くの高度なシェル機能と同様に、もともとksh機能であり、bashとzshで採用されました。psub
具体的には魚の機能であり、POSIXとは関係ありません。
プロセスの置換は<(command)
、の出力をcommand
ファイルとして使用するform に限定されないことに注意してください。>(command)
ファイルを入力として供給する形式にすることもできますcommand
。これは、@ enzotibの回答のbashマニュアルの引用にも記載されています。
date | cat
上記の例では、フォームのプロセス置換を使用し>(command)
て同じ効果を達成するコマンドは、
date > >(cat)
>
前>(cat)
が必要であることに注意してください。これはecho
、@ Calebの回答のように、再び明確に説明できます。
$ echo >(cat)
/dev/fd/63
したがって、余分な>
がdate >(cat)
なければ、date /dev/fd/63
メッセージはstderrに出力されます。
パラメータとしてファイル名のみを使用し、stdin
またはを処理しないプログラムがあるとしますstdout
。psub.sh
これを説明するために、単純化しすぎたスクリプトを使用します。の内容psub.sh
は
#!/bin/bash
[ -e "$1" -a -e "$2" ] && awk '{print $1}' "$1" > "$2"
基本的には、両方の引数がファイル(必ずしも通常のファイルである必要はない)であることをテストし、その場合は、awk "$1"
を"$2"
使用して各行の最初のフィールドに書き込みます。次に、これまでに述べたすべてを組み合わせたコマンドは、
./psub.sh <(printf "a a\nc c\nb b") >(sort)
これは印刷されます
a
b
c
と同等です
printf "a a\nc c\nb b" | awk '{print $1}' | sort
しかし、以下は機能せず、ここでプロセス置換を使用する必要があります。
printf "a a\nc c\nb b" | ./psub.sh | sort
またはその同等の形式
printf "a a\nc c\nb b" | ./psub.sh /dev/stdin /dev/stdout | sort
上記のもの以外に./psub.sh
も読み取る場合stdin
、そのような同等のフォームは存在せず、その場合、プロセス置換の代わりに使用できるものはありません(もちろん、名前付きパイプまたは一時ファイルを使用することもできますが、それは別のものです物語)。