Process Substitution
GNU Bash Manual 3.5.6 Process Substitution
>(list)
プロセスをファイルとして、そこに他のstdout/stderrをファイルとして書き出せる。
$ cat <<EOF > >(grep -v b)
> a
> b
> c
> EOF
a
c
grep -v b
がasyncに実行され、/dev/fd/xxx (xxxは番号)のファイルとして待ち構えている (async)- catのstdoutをファイル(
>(...)
で実行されているプロセス)にリダイレクト - catからリダイレクトされた3行がファイル = "grepのプロセス"に書き込まれる
b
以外のa
、c
がgrepのプロセスによって出力される
run_app.sh 2> >(tee log)
のようにすれば、run_app.shのプロセスのstdoutはそのまま出力され、stderrをteeプロセスに書き込みながらlogにも保存できる。
run_app.sh実行時はerror yyy
(stderr)、info xxx
(stdout)の順のだとしても、run_app.shのstdoutとteeのstdoutは出力順が前後することがあるのは、process substitutionで実行されたプロセスはasyncに実行されるため。
<(list)
プロセスのstdout/stderrをファイルとして、そのファイルを他のコマンドの引数にできる。
$ A="a
b
c"
$ B="a
x
c"
$ diff -u <(echo "$A") <(echo "$B")
--- /dev/fd/63 2020-09-26 07:12:48.000000000 +0900
+++ /dev/fd/62 2020-09-26 07:12:48.000000000 +0900
@@ -1,3 +1,3 @@
a
-b
+x
c
結果からわかるようにecho "$A"
の出力が/dev/fd/63というファイルとして保存され、そのファイルをdiffの1つ目のファイルとしている。<(...)
で実行されるプロセスが重い場合、ファイルのEOF = プロセスの終了まで読むのでブロッキングが発生する。複数の<(...)
を一度に実行(上のdiffはその例)してもすべてasyncに実行されるので待ちの最大は一番重いプロセスの実行時間となる。
Note
< (
とスペースを空けるとsyntax error (そりゃそうだ。redirectionじゃない。)- multilinesのvariableに対し、
echo $A
とecho "$A"
の違いにつまずきがち