このようなスクリプトがあるとしましょう。
#!/bin/bash
set -e
ls notexist && ls notexist
echo still here
set -e のために終了しません
しかし
#!/bin/bash
set -e
ls notexist || ls notexist
echo still here
意思。なんで?
bashマニュアルには次のように書かれていset -e
ます:
The shell does not exit if the command that fails is [...]
part of any command executed in a && or || list except the
command following the final && or ||
ダッシュのマニュアルには次のように書かれています。
If not interactive, exit immediately if any untested command fails.
The exit status of a command is considered to be explicitly tested
if the command is used to control an if, elif, while, or until;
or if the command is the left hand operand of an “&&” or “||” operator.
ANDテストの場合、シェルは「左側のオペランド」のテスト中に早期に停止します。まだテストがあるため、コマンド全体が「テスト済み」であると見なされ、中止されません。
ORテストの場合、シェルはすべての (両方の) テストを実行する必要があり、最後のテストが失敗すると、チェックされていないエラーがあったと判断され、中止されます。
少し直感に反することに同意します。
Bash のマニュアルにあるようにset -e
:
失敗したコマンドが、while または until キーワードの直後のコマンド リストの一部である場合、if または elif 予約語に続くテストの一部である場合、&& または || で実行されるコマンドの一部である場合、シェルは終了しません。最後の && または || に続くコマンド、パイプライン内の最後のコマンド以外のコマンド、またはコマンドの戻り値が ! で反転されている場合を除きます。
ls notexist || ls notexist
2 番目 (最後) のコマンドが正常に終了しないため、このコマンドはシェルをls notexist
終了します。「ls notexist && ls notexist
&& list」の実行は、最初のls notexist
失敗後に停止され、2 番目 (最後) のリストに到達しないため、シェルは終了しません。
ところで、 などの特定のコマンドの代わりにtrue
andを使用して、このようなテストを行う方が簡単で信頼性が高くなります。false
ls notexist