解説
前が失敗したら次を動かしたくない:Bashの&&・||・;を使い分けよう
セミコロン、成功時の&&、失敗時の||を、書込みのない小さなBash例で比較。最後に実行した状態と、ifの代用品にする注意も整理。

一つ目のコマンドに失敗したのに、次の処理が動いてしまった。Bashでは、コマンドを何でつなぐかによって、次を実行する条件が変わるよ。
今回はファイルを作らず、true・false・printfだけで比較する。Bashを使える端末を対象に、表示される行と終了状態を見てみよう。
セミコロンは、成功したときだけの指定ではない
コマンドを;で区切ると、通常は前の処理が終わってから次へ進む。前の終了状態が0だった場合だけ実行する、という条件は付かない。
一方、&&は左側の並びが成功した場合に右側を実行し、||は失敗した場合に右側を実行するよ。Bashでは終了状態0が成功、それ以外を失敗として扱う。
| つなぎ方 | 次の処理へ進む条件 |
|---|---|
| ; | 成功・失敗の条件を付けず順に進む |
| && | 左側が成功した場合 |
| || | 左側が失敗した場合 |
小さな例をまとめて試す
カッコ内は別のシェル環境で動かす。set +eはこの中だけで、失敗のあとも結果を観察するために使い、元のシェル設定へは影響しないよ。
(
set +e
false; printf 'semicolon:next\n'
false && printf 'and:next\n'
printf 'and-status:%s\n' "$?"
false || printf 'or:fallback\n'
true && false || printf 'chain:fallback\n'
)
期待する表示は次の四行。
semicolon:next
and-status:1
or:fallback
chain:fallback
and:nextは表示されない。左のfalseが失敗したため、その右は実行されないんだ。and-status:1は、その並びを直後に見た終了状態だよ。
&&と||の連結を、単純なifの代わりにしない
最後の例は、最初がtrueなのにchain:fallbackが表示される。最初の条件が成功しても、次のfalseが失敗し、そのあとの||が実行されるからだよ。
成功側の処理そのものが失敗する場合もあるので、「条件 && 成功処理 || 失敗処理」をいつでもif・elseと同じだと考えないようにしよう。複雑になるなら、条件と処理をifで明示したほうが読みやすいね。
文字を次へ渡すパイプとは別
&&や||は、次のコマンドを動かす条件を扱う。標準出力を次の標準入力へ渡す|とは違う仕組みだよ。
また、&&でつないだから、すでに行った変更が失敗時に自動で元へ戻るわけでもない。更新や公開を行うスクリプトでは、事前確認、対象範囲、失敗時の復元を別に考える必要があるね。

みんなのコメント 0
感想や、試してみたことを聞かせてね。コメント・返信は承認後に公開されます。
最初のコメントをどうぞ。