我有很长的命令,大致是这样的:
$ command-outer "long command which references a file here: filename1, and another file reference here: filename2"
这些文件是另一个命令的输出。所以我正在做:
$ command-outer "long ... "<(command-inner "again long params")"... "\
<(command-inner "again long params")" ..."
为了便于阅读,我想<()
从长命令调用中提取内部未命名/匿名管道(带有 的管道)。但我似乎不能这样做;执行以下操作:
RESULT_FILE_DESCRIPTOR1=<(command-inner ....)
RESULT_FILE_DESCRIPTOR1
导致当我实际在参数列表中使用时文件描述符已经被关闭command-outer
并command-outer
在同一行调用,因此:
RESULT_FILE_DESCRIPTOR1=<(command-inner ....) outer-command "long ... $RESULT_FILE_DESCRIPTOR1 ... "
返回一个空结果 RESULT_FILE_DESCRIPTOR1,这并不奇怪,因为:
FOO=BAR echo $FOO
也不起作用。
答案1
您可以只命名命令,而不是命名结果。
param_set_1(){
input_command \
-lots \
-of \
-params
}
param_set_2(){
input_command \
-lots \
-of \
-other \
-params
}
command_outer -params <(param_set_1) <(param_set_2)
您还可以经常按名称引用文件描述符。
param_set_1 | { param_set_2 | command_outer -params /dev/fd/3 -; } 3<&0
如果您确实想要当前 shell 变量中的结果和在文件描述符中,那么你应该避开管道。您冒着用命令的输出填充管道缓冲区的风险,同时尝试将这些结果分配给父 shell 变量,然后管道缓冲区可以被读取过程耗尽......好吧,这并不漂亮。因此,您应该一次性完成所有内容,并使用此处文档。
unset fd3 fd4
{ command_outer -params /dev/fd/[34]
} 3<<FD3 4<<FD4
${fd3=$(param_set_1)}
FD3
${fd4=$(param_set_2)}
FD4
答案2
您可以显式使用命名管道(我认为进程替换确实在细节中使用了命名管道):
trap cleanup EXIT
cleanup() { rm -f "$inner1" "$inner2"; }
inner1=$(mktemp -u) && mkfifo "$inner1"
command-inner "again long params" > "$inner1" &
inner2=$(mktemp -u) && mkfifo "$inner2"
command-inner "again long params" > "$inner2" &
command-outer "long ... $inner1... $inner2 ..."