私set -e
は最初のエラーでbashスクリプトを停止する。
次のコマンドを使用しない限り、すべて正常に動作します&&
:
$ cat script
set -e
cd not_existing_dir && echo 123
echo "I'm running! =P"
$
$ ./script
./script: line 2: cd: not_existing_dir: No such file or directory
I'm running! =P
$
と比べて:
$ cat script
set -e
cd not_existing_dir
echo "I'm running! =P"
$
$ ./script
./script: line 2: cd: not_existing_dir: No such file or directory
$
最初の例ではまだエコーしますI'm running!
が、2 番目の例ではエコーしません。なぜ動作が異なるのでしょうか?
UPD。同様の質問:https://stackoverflow.com/questions/6930295/set-e-and-short-tests
答え1
これは文書化された動作です。bash(1) マニュアルページ言う、set -e
、
失敗したコマンドが、
while
またはキーワードの直後のコマンドリストの一部である場合、または予約語のuntil
またはの後のテストの一部である場合、シェルは終了しません。if
elif
&&
または||
リスト内で実行されるコマンドの一部 最後&&
のまたは||
、パイプライン内の最後以外のコマンド、またはコマンドの戻り値が で反転されている場合!
。
[強調追加]
そしてそのPOSIXシェルコマンド言語仕様 これが正しい動作であることを確認します。
、、、または予約語に続く複合リスト、予約語で始まるパイプライン、または最後以外の AND-OR リストのコマンドを実行する場合、設定
-e
は無視されます。while
until
if
elif
!
そしてセクション2.9.3リストその文書は定義している
AND-OR リストは、演算子 "
&&
" と "||
" で区切られた 1 つ以上のパイプラインのシーケンスです。
答え2
このset -e
オプションは状況によっては効果がありませんが、これは標準的な動作であり、POSIX 準拠のシェル間で移植可能です。
失敗したコマンドはパイプラインの一部です:
false | true; echo printed
印刷されますprinted
。
パイプライン自体の障害のみが考慮されます。
true | false; echo 'not printed'
何も印刷されません。
while
失敗したコマンドは、予約語、予約語で始まるパイプライン、または最後のコマンドを除くリストまたはリストuntil
の一部である任意のコマンドに続く複合リストで実行されました。if
elif
!
&&
||
false || true; echo printed
最後のコマンドが失敗しても、set -e
影響は残ります:
true && false; echo 'not printed'
のサブシェル複合コマンドで失敗します:
(false; echo 'not printed') | cat -; echo printed
答え3
私の推測では、if-then 条件全体は true と評価されます。
私は試した
set -e
if cd not_existing_dir
then echo 123
fi
echo "I'm running! =P"
与える人
-bash: cd: not_existing_dir: No such file or directory
I'm running! =P
エラー コードは if 条件によってキャッチされるため、bash は実行の終了をトリガーしません。