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