El Capitan より前の SuSE 11.3 と Mac OS の両方で、bash バージョン 3.2.51 でこの動作を確認しました。El Capitan の Bash 3.2.57 は、bash 4 のような「正しい」動作をします。
ただし、上記で提案された回避策は、「|| exit $?」を追加します。サブシェルの閉じ括弧の後に、bash のバージョンに関係なく、-e フラグの意図が無効になります。マンバッシュから:
-e 単純なコマンド (上記のシェル文法を参照) がゼロ以外のステータスで終了した場合、すぐに終了します。失敗したコマンドが、while または until キーワードの直後のコマンド リストの一部である場合、if ステートメントのテストの一部である場合、&& または || の一部である場合、シェルは終了しません。リスト、...
「|| exit $?」が続くサブシェル 明らかにコマンドリストとしてカウントされます。また、bash -e フラグは、サブシェル内のコマンドには適用されません。それを試してみてください:
$ set -e
$ ( echo before the error; false; echo after the error, status $?; ) || echo after the subshell, status $?
before the error
after the error, status 1
$
サブシェルの後には || が続くため、set -e を使用しても「エラー後のエコー」が実行されます。それだけでなく、その「エコー」が実行されたため、サブシェルは 0 で終了します。つまり、「|| $ を終了しますか?」「出口」さえ実行しません。おそらく私たちが望んでいたものではありません!
私の知る限り、次の式は、サブシェルの後に bash -e を受け入れるかどうかに関係なく、bash バージョンと互換性があります。-e フラグがたまたまリセットされた場合でも、正しく動作します。
bash スクリプトのすべてのサブシェルの閉じ括弧の直後に次の行を追加します。
case $?/$- in ( 0/* ) ;; ( */*e* ) exit $? ;; esac # honor bash -e flag when subshell returns