LinuxやmacOSなどのターミナル環境でBashを利用する際、複数のコマンドを1行で連続して実行したい場面は多々あります。
その際、何気なく使っている「;(セミコロン)」と「&&(アンパサンド2つ)」には、実行の継続条件において決定的な違いが存在します。
2026年現在、クラウドネイティブな環境や自動化スクリプトの重要性が増す中で、これらの記号の使い分けを誤ると、不完全なデータ処理や予期せぬシステムの破壊を招くリスクがあります。
本記事では、これら2つの記号の挙動を深く理解し、堅牢なスクリプトを書くためのエラーハンドリングの鉄則について詳しく解説します。
コマンドを繋ぐ2つの記号:基本的な考え方
Bashにおけるコマンドの連結は、単に「並べて実行する」だけではありません。
それぞれの記号は「前のコマンドの結果をどう扱うか」という制御フローの役割を担っています。
セミコロン(;)による逐次実行
セミコロンは、複数のコマンドを単純に並べて実行するために使用されます。
最大の物理的特徴は、「前のコマンドが成功したか失敗したかに関わらず、次のコマンドを必ず実行する」という点にあります。
これは、手動でコマンドを入力した後に「Enterキー」を押し、実行が終わったら次のコマンドを入力して「Enterキー」を押す、という動作を1行にまとめたものと同じです。
# ディレクトリを作成し、その中へ移動し、現在のディレクトリを表示する
mkdir sample_dir ; cd sample_dir ; pwd
上記の例では、たとえ mkdir が失敗したとしても、シェルは次の cd コマンドを試み、その成否に関わらず最後の pwd を実行します。
論理積(&&)による条件付き実行
一方で「&&」は、プログラミングにおける論理積(AND)と同じ性質を持ちます。
Bashにおいては、「前のコマンドが成功(正常終了)した場合のみ、次のコマンドを実行する」という挙動をします。
Bashの世界では、コマンドが成功すると「終了ステータス」として 0 を返します。
&& は、この終了ステータスが 0 であることを確認してから右側のコマンドへ処理を移します。
# ディレクトリの作成に成功した場合のみ、その中へ移動する
mkdir sample_dir && cd sample_dir
もし mkdir が何らかの理由(権限不足や既に同名のファイルが存在するなど)で失敗した場合、cd コマンドは実行されません。
これにより、意図しないディレクトリでの操作を防ぐことができます。
動作の違いを比較表で整理
これら2つの演算子の違いを明確にするために、実行条件と主な用途を以下の表にまとめました。
| 演算子 | 名称 | 実行条件 | 主な用途 |
|---|---|---|---|
; | セミコロン | 前の成否に関わらず実行 | 独立した関連性の低いコマンドの連続実行 |
&& | 論理積(AND) | 前が成功した場合のみ実行 | 依存関係がある処理の連鎖、安全な実行 |
この違いを理解することが、エラーに強いシェルスクリプトへの第一歩となります。
実践:エラーハンドリングの鉄則
なぜ Bash において && の使い分けが重要視されるのか、具体的なリスクを想定して考えてみましょう。
もっとも危険なシナリオの一つは、「移動に失敗したのに削除コマンドが走る」ケースです。
なぜ && を使うべきなのか? 惨劇を防ぐコード例
以下の2つの例を比較してください。
特定の作業ディレクトリに移動して、その中身を一括削除するスクリプトを想定します。
危険な例(セミコロンを使用)
# 作業ディレクトリへ移動し、中身を全て削除する
cd /tmp/work_dir ; rm -rf *
もし /tmp/work\_dir が存在しなかった場合、cd はエラーになります。
しかしセミコロンを使っているため、処理は止まらずに rm -rf * が実行されます。
その結果、移動前のカレントディレクトリ(最悪の場合はホームディレクトリなど)のファイルが全て消去されるという惨事につながります。
安全な例(&& を使用)
# 移動に成功した場合のみ、削除を実行する
cd /tmp/work_dir && rm -rf *
&& を使用していれば、もし /tmp/work\_dir への移動に失敗した時点で処理が中断されます。
後続の rm コマンドは実行されないため、大切なデータを守ることができます。
終了ステータス($?)との関係
Bashのすべてのコマンドは、終了時に「0から255」の範囲で終了ステータスを保持します。
この値は特殊変数 $? で確認できます。
- 0:成功(正常終了)
- 0以外:失敗(異常終了、エラー発生)
&& は、この $? が 0 であるかどうかを内部的に評価しています。
デバッグを行う際は、以下のようにステータスを確認する癖をつけると良いでしょう。
ls nonexistent_file
# 終了ステータスを表示
echo $?
ls: nonexistent_file: No such file or directory
2
このように ls が失敗して 2 を返した場合、&& で繋がれた次のコマンドはスキップされます。
応用編:&& と || を組み合わせた制御
&& と対になる演算子に「||(論理和 / OR)」があります。
これは 「前のコマンドが失敗した場合のみ、次のコマンドを実行する」という挙動をします。
これらを組み合わせることで、簡易的な条件分岐(if-then-elseのような動作)を1行で記述することが可能です。
成功と失敗で処理を分ける
# コマンドを実行し、成功なら「OK」、失敗なら「NG」を表示する
./run_task.sh && echo "Task Succeeded" || echo "Task Failed"
この記法はログ出力や通知処理によく使われます。
ただし、注意点として、左側の && の後のコマンド(この場合は echo "Task Succeeded")自体が失敗した場合、右側の || 以降も実行されてしまいます。
複雑な条件分岐が必要な場合は、無理に1行で書かず if 文を使用するのが2026年現在のベストプラクティスです。
複雑なコマンド連結とグループ化
複数のコマンドを連結する際、実行順序を制御したい場合があります。
その場合は、丸括弧 ( ) や波括弧 { } を使ってグループ化を行います。
サブシェルでの実行 ( )
丸括弧で囲むと、その中のコマンドは「サブシェル」と呼ばれる別プロセスで実行されます。
そのため、中でのディレクトリ移動(cd)や変数定義は、元のシェルには影響を与えません。
# サブシェル内でディレクトリ移動と作業を行う
(cd /var/log && tar -czf logs.tar.gz *.log) && mv /var/log/logs.tar.gz ./backup/
現在のシェルでのグループ化 { }
波括弧を使用すると、現在のシェルプロセスを維持したままコマンドをグループ化できます。
# 複数のコマンドを一括りで扱い、成否によって後続を制御する
{ grep "ERROR" app.log && mail -s "Alert" admin@example.com ; } || echo "No action needed"
※波括弧を使用する場合、末尾のコマンドの後にセミコロン ; または改行が必要であり、括弧の内側にスペースが必要という文法上の制約があります。
スクリプトの堅牢性を高める 2026 年のベストプラクティス
現代のシステム運用において、シェルスクリプトの役割は依然として重要です。
特に、CI/CDパイプラインやコンテナオーケストレーション(Kubernetesなど)の定義ファイル内で、複数のコマンドを連結して記述する機会が増えています。
set -e との使い分け
スクリプト全体で「エラーがあったら即座に終了する」という設定にするため、スクリプトの冒頭に set -e を記述することが推奨されます。
しかし、set -e を有効にしている場合でも、&& や || で繋がれたコマンドの途中経過については、即座に終了せずに評価が続けられます。
- スクリプトファイル内: 原則として
set -eを使いつつ、個別のリカバリが必要な箇所で||を使う。 - ワンライナー・コマンドライン: 常に
&&を使用して、前の手順の成功を担保する。
読みやすさを維持する
いくら && が便利だからといって、10個以上のコマンドを1行で繋ぐのは避けるべきです。
可読性が著しく低下し、どこでエラーが発生したかの追跡が困難になります。
# 読みづらい例
step1 && step2 && step3 && step4 && step5 && step6
# 改善例(バックスラッシュで改行)
step1 \
&& step2 \
&& step3 \
&& step4
このように、論理的な区切りで改行を入れることで、後からコードを読む人が「この処理は一連の成功が必要なのだな」と即座に理解できるようになります。
まとめ
Bashにおける「;」と「&&」の使い分けは、単なる好みの問題ではなく、システムの安全性と信頼性に直結する重要な技術です。
- セミコロン(;)は、各コマンドが独立しており、前の結果に関わらず次へ進みたい場合に使用する。
- アンパサンド2つ(&&)は、前のコマンドの成功が次を実行するための前提条件である場合に使用する。
- エラーハンドリングの鉄則として、ディレクトリ移動や破壊的な操作(削除・上書き)を伴う場合は、必ず && を使用する。
2026年のエンジニアリングにおいても、これらの基礎的なシェル操作の習熟度は、トラブルの少ない安定したシステム運用の基盤となります。
この記事を参考に、日々の作業やスクリプト作成において、より安全なコマンド連結を心がけてみてください。
