假设我有这样的命令:
foo() {
echo a
echo b >&2
echo c
echo d >&2
}
我使用以下命令在终端中处理标准输出,但通过通知发送发送错误
foo 1> >(cat) 2> >(ifne notify-send "Error")
我遇到的问题是,我想将 stderr (在本例中b d
)视为通知发送正文。
我努力了:
foo 1> >(cat) 2> >(ifne notify-send "Error" "$(cat)")
foo 1> >(cat) 2> >(ifne notify-send "Error" "$(</dev/stdin)")
什么都不起作用。这里有什么解决办法呢?
答案1
通过您的尝试,"$(cat)"
您已经快完成了,但是您需要cat
从 读取ifne
,而不是沿着 读取ifne
。
在 的情况下ifne notify-send "Error" "$(cat)"
,会cat
从同一流读取ifne
,但不同时读取。处理这部分代码的 shellifne
只能在退出后运行cat
(因为只有这样它才知道$(cat)
应该扩展到什么,即fine
应该得到什么参数)。退出后cat
,流已耗尽,并且ifne
其输入为空。
这是一种进行类似使用的cat
读取的方法ifne
:
foo 2> >(ifne sh -c 'exec notify-send "Error" "$(cat)"')
(我不确定你的目的1> >(cat)
是什么。我跳过了。)
这里ifne
将其输入中继到它(有条件地)运行的任何内容的标准输入。它是sh
,但它sh
运行的所有内容都共享其标准输入。有效地cat
读取自ifne
.和你的try类似,exec notify-send
只能在cat
退出后执行;因此,即使notify-send
尝试从其标准输入中读取,cat
也会首先消耗所有内容。
如果传递的数据过多,此方法可能会失败cat
。参数列表不能任意长。并且因为cat
只有在退出后才会退出foo
,所以该方法适用于foo
退出并且不会向其 stderr 生成太多消息。
对于长时间运行来说,使用xargs
代替可能是一个好主意$(cat)
foo
使用偶尔产生一行错误。这是这样的一个例子foo
:
foo() {
echo a
echo b >&2
sleep 10
echo c
echo d >&2
sleep 20
}
在这种情况下,上述解决方案不一定好foo
(尝试一下)。有了xargs
它就不同了。foo
甚至可能无限期地运行,并且您将立即收到错误通知(一次一行)。如果你xargs
支持--no-run-if-empty
( -r
)那么你就不需要ifne
。这是一个示例命令xargs
:
foo 2> >(xargs -r -I{} notify-send "Error" {})
(请注意,这xargs
仍然解释引号和反斜杠。)