bash:将stdout捕获到一个variables,但仍然显示在控制台中

我有一个bash脚本,它调用几个长时间运行的进程。 我想将这些调用的输出捕获到variables中,以便处理。 但是,由于这些是长时间运行的进程,所以我希望将rsync调用的输出实时显示在控制台中,而不是事后。

为此,我已经find了一种方法,但它依赖于将文本输出到/ dev / stderr。 我觉得输出到/ dev / stderr不是做事的好方法。

VAR1=$(for i in {1..5}; do sleep 1; echo $i; done | tee /dev/stderr) VAR2=$(rsync -r -t --out-format='%n%L' --delete -s /path/source1/ /path/target1 | tee /dev/stderr) VAR3=$(rsync -r -t --out-format='%n%L' --delete -s /path/source2/ /path/target2 | tee /dev/stderr) 

在上面的例子中,我调用rsync几次,我想看看他们处理的文件名,但最后我仍然希望在一个variables的输出,因为我会稍后parsing它。

是否有一个“更干净”的方式来完成这个?

如果它有所作为,我使用Ubuntu 12.04,bash 4.2.24。

在shell中复制&1(在我的例子中为5)并在子shell中使用&5(以便您将写入父shell的stdout(&1)):

 exec 5>&1 FF=$(echo aaa|tee >(cat - >&5)) echo $FF 

将打印aaa两次,因为subhell中的回显,第二次打印variables的值。

在你的代码中:

 exec 5>&1 VAR1=$(for i in {1..5}; do sleep 1; echo $i; done | tee >(cat - >&5)) # use the value of VAR1 

Op De Cirkel的答案有正确的想法。 它可以更简化(避免使用cat ):

 exec 5>&1 FF=$(echo aaa|tee /dev/fd/5) echo $FF 

这是一个捕获stderr和命令退出代码的例子。 这是罗素·戴维斯(Russell Davis)的回答。

 exec 5>&1 FF=$(ls /taco/ 2>&1 |tee /dev/fd/5; exit ${PIPESTATUS[0]}) exit_code=$? echo "$FF" echo "Exit Code: $exit_code" 

如果文件夹/taco/存在,这将捕获其内容。 如果文件夹不存在,则会捕获错误消息,退出代码将为2。

如果你忽略2>&1那么只有stdout会被捕获。

您可以使用三个以上的文件描述符。 试试这里:

http://tldp.org/LDP/abs/html/io-redirection.html

“每个打开的文件都被分配了一个文件描述符[2] stdin,stdout和stderr的文件描述符分别为0,1和2,打开其他文件时,保留描述符3到9。将其中一个附加文件描述符分配给stdin,stdout或stderr作为临时重复链接。

重点是为了达到这个结果,是否值得让脚本更复杂。 其实这不是真的错,你这样做。