びっくりしたのでメモ。
bash スクリプトで set -e
と関数と ||
を組み合わせると、関数内では set -e
が無効になります。嘘のようですが本当です。
例えば以下のスクリプトは end f
が出力されず start
, start f
, ng
, end
が出力されそうに見えます。
が、実際には ng
が出力されず end f
が出力されます。
set -e
f() {
echo "start f"
false
echo "end f"
}
echo "start"
f || echo "ng"
echo "end"
結果:
start
start f
end f
end
なかなかに不可解です。
どうすればよいのか
f
を関数ではなく別コマンドとするか、set -e
に頼らず真面目にエラー処理をするのがよいと思います。
それらしい回答
質問の例ですとfalseは関数中では単独で呼び出されていますが、その関数を呼び出しているのは&&を含んだコマンド列ですので、
&& または || によるコマンドのリストの一部
という事になるのだと思います。
Indeed, the correct behavior mandated by POSIX (namely, that 'set -e' is completely ignored for the duration of the entire body of f(), because f was invoked in a context that ignores 'set -e') is not intuitive. But it is standardized, so we have to live with it.
僕らはPOSIXと共に生きなければいけないのです。不可解でも納得しましょう。