次のようなコマンドがあるとしましょう。
foo() {
echo a
echo b >&2
echo c
echo d >&2
}
次のコマンドを使用して端末でstdoutを処理していますが、通知を介してエラーが送信されます。
foo 1> >(cat) 2> >(ifne notify-send "Error")
b d
私が経験している問題は、stderr(この場合)を通知送信の本文として処理したいということです。
私は試した:
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
同時には行われません。コードのこの部分を処理するシェルはifne
終了後にのみ実行できます。なぜなら、それ以降に拡張する必要がある項目、つまりどの引数を取得するのかをcat
知ることができるからです。終了後、ストリームはすべて消費され、対応する入力は空です。$(cat)
fine
cat
ifne
以下を使用してcat
読み取りを実行する方法は次のとおりですifne
。
foo 2> >(ifne sh -c 'exec notify-send "Error" "$(cat)"')
(何が目的なのかよくわかりません1> >(cat)
。スキップしました。)
これは、ifne
(条件付きで)実行中のすべての項目の標準入力に入力を渡します。ただし、実行されるすべての項目sh
はsh
標準入力を共有します。cat
で効果的に読みますifne
。試みと同様に、終了した後に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
無制限に実行される可能性があり、エラーがある場合はすぐに通知を受け取ります(一度に1行ずつ)。 ()をxargs
支持するならば、それは必要ありません。以下はコマンドの例です。--no-run-if-empty
-r
ifne
xargs
foo 2> >(xargs -r -I{} notify-send "Error" {})
(これはxargs
まだ引用符とバックスラッシュを解釈します。)