Bash中的"> (tee -a ...)"命令

3

我有这段 Bash 代码,它运行 Scala 测试代码:

scripts=(
Hello.scala
)

for script in "${scripts[@]}"; do
    echo scala "${script}"
    scala -nocompdaemon "${script}" > >(tee -a _testoutput.txt) \
        2> >(tee -a _testerrors.txt >&2)
done

我该如何解释 >(tee -a _testoutput.txt)?通常我使用管道符号|来使用tee命令。使用这个表达式有什么区别呢?
2个回答

4

在这种情况下,我认为> >(tee -a _testoutput.txt)| tee -a _testoutput.txt的行为是相同的。

显然需要标准错误版本,因为没有标准错误管道。

管道版本和过程替换>(...))版本之间的另一个主要区别是子shell发生的位置。

例如,如果>(...)适用于整个循环,并且您需要在循环中设置的变量持续存在于循环外部,则无法使用管道版本(有关此更多信息,请参见Bash FAQ 24)。

另一个不同之处,正如Charles Duffy所指出的, 是管道会影响管道的退出状态(默认情况下,您会得到管道中最后一个命令的退出状态,尽管set -o pipefail会改变这一点,而Bash PIPESTATUS数组包含所有退出状态)。另一方面,进程替换不会影响退出状态。


2
另一个区别是退出状态; > >(tee -a foo) 不会改变退出状态,而 | tee -a foo 会。 - Charles Duffy
1
使用进程代替可能会有一些警告:如果被代替的进程提前完成并且主进程仍然想要写一些内容,那么接收 SIGPIPE 信号的将是主进程本身:{ sleep 1; echo a; } > >(:) - gniourf_gniourf

3

>( list ) 被称为 "进程置换"。它比普通管道更强大: 你不能轻松地使用 | 将标准输出和标准错误重定向到不同的程序中。


你可以使用管道将标准输出和标准错误重定向到不同的程序,使用适当的重定向。这有点丑陋,但是可以做到而不会有任何主要的注意事项。 - gniourf_gniourf
1
@gniourf_gniourf:没错,使用2>&7等命令是可以的。已更新。 - choroba

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接