不足しているコマンドによるマルチパイプ損傷の防止

不足しているコマンドによるマルチパイプ損傷の防止

シェルスクリプトでは、次のように複数のパイプを使用することがよくあります。

cmd1 | cmd2 | cmd3

パイプが存在しない場合、cmd2「損傷」が発生し、cmd3入力は受信されません。

回避策としてcmd2が存在するかどうかを明示的にテストできますが、これには避けたいコードの重複が必要です。

代わりに、次のようにもう少し簡潔なテストをしたいと思います。

cmd1 | cmd2; [ $? -eq 127 ] && cat | cmd3

答え1

より簡潔にするために、ミニ関数を書くことができます。

ifexists(){
    if command -v "$1"
    then "$@"
    else echo "doing cat for missing $1" >&2
         cat
    fi
}

echo hi | ifexists mycommand | cat -n

答え2

|あなたの例によれば、(および&&)よりも優先順位の低いタスクの||パラメータをグループ化する方法を探しているようです。

{メタ文字を}使用してこのようにグループ化できます。

上記の例は次のように書くことができます(終了ステータスを使用して存在することをwhich確認cmd2)。

cmd1 | { which cmd2 >/dev/null && cmd2 || cat; } | cmd3

例えば

printf "hi\n" | { : && rev || cat; } | cat

印刷されますih

サブシェルの使用に関する提案も機能しますが、不必要に別のプロセスを使用します。

printf "hi\n" | ( : && rev || cat ) | cat

ifパイプの外側で明示的に使用することは、あまりトリッキーでメンテナンスが容易になると言いたいです。

if [ which cmd2 >/dev/null ]
then
    cmd1 | cmd3
else
    cmd1 | cmd2 | cmd3
fi

関連情報