バッチファイルで「エラーが発生したか」を判定する方法は、単に ERRORLEVEL を見ればよいという話ではありません。
ERRORLEVEL は直前に実行されたコマンドが返した終了コードであり、コマンドごとに「0 以外=失敗」の意味が異なることもあります。
そのため実務では、どのコマンドの結果を判定しているかを明確にし、判定結果に応じた後処理まで含めて設計することが重要です。
ERRORLEVELで判定する基本形
最も基本となるのは、対象コマンドの直後で ERRORLEVEL を評価し、0 なら正常、0 以外なら異常として扱う形です。
重要なのは、判定の前に余計なコマンドを挟まず、必ず「直後」で評価することです。
@echo off
somecommand
if %ERRORLEVEL% neq 0 (
echo エラーが発生しました
exit /b 1
)
echo 正常に完了しました
exit /b 0
ここで exit /b を返す値は、呼び出し元がさらに上位で判定する場合の戻り値になります。
if ERRORLEVEL構文で判定する場合の注意
if ERRORLEVEL は便利ですが、判定仕様が「等号」ではなく指定値以上である点に注意が必要です。
0/非0 の二択で使う場合は誤解が少ない一方、複数コードを扱うときは必ず大きい数値から判定する必要があります。
@echo off
somecommand
if errorlevel 1 (
echo エラーが発生しました
exit /b 1
)
echo 正常に完了しました
exit /b 0
この形なら「1 以上=エラー」として扱えるため、運用上は読みやすくなります。
「エラーではないのに1になる」コマンドを区別する
find や findstr は、処理として失敗していなくても、検索対象が見つからないだけで ERRORLEVEL=1になります。
この場合、1 を「検索結果なし」として扱う設計が必要です。
@echo off
find "ABC" sample.txt > nul
if %ERRORLEVEL% equ 0 (
echo 見つかりました
) else if %ERRORLEVEL% equ 1 (
echo 見つかりませんでした
) else (
echo 読み取りエラーなどが発生しました
exit /b 2
)
このように、エラーコードの意味がコマンド仕様に依存する場合は、0/非0 の単純判定を避けるのが安全です。
パイプ処理は最後のコマンドの結果になる
パイプ(|)を使うと、ERRORLEVEL は最後のコマンドの終了コードになります。
前段の成否を判定したい場合、パイプを分解して個別に評価する方が確実です。
@echo off
type sample.txt > nul
if %ERRORLEVEL% neq 0 (
echo ファイル読み取りに失敗しました
exit /b 1
)
find "ABC" sample.txt > nul
if %ERRORLEVEL% equ 0 (
echo 見つかりました
) else if %ERRORLEVEL% equ 1 (
echo 見つかりませんでした
) else (
echo 検索処理でエラーが発生しました
exit /b 2
)
エラー判定の精度を上げたい場面ほど、パイプのまま判定しない設計が安定します。
括弧ブロック内でのERRORLEVEL参照
括弧ブロック内で %ERRORLEVEL% を参照すると、状況によっては値が固定されて見えることがあります。
状態の変化をブロック内で追跡する場合は、遅延環境変数展開を有効にし、!ERRORLEVEL! を使う方が安全です。
@echo off
setlocal enabledelayedexpansion
somecommand
if !ERRORLEVEL! neq 0 (
echo エラーが発生しました
exit /b 1
)
echo 正常に完了しました
exit /b 0
サブルーチン化するなら戻り値を設計する
call :label でサブルーチン化すると、ERRORLEVEL は呼び出し元に引き継がれます。
サブルーチンの末尾で exit /b を明示しないと、意図しないコードが残り、エラー判定が壊れます。
@echo off
call :do_work
if %ERRORLEVEL% neq 0 (
echo do_workでエラー
exit /b 1
)
echo 全体正常
exit /b 0
:do_work
somecommand
if %ERRORLEVEL% neq 0 exit /b 1
exit /b 0
サブルーチンは「成功時は 0、失敗時は 1 以上」を返すと、上位が安定して判定できます。
まとめ
バッチファイルでエラー発生を判定する基本は、対象コマンドの直後に ERRORLEVEL を評価し、必要なら exit /b で戻り値を明示することです。
ただし、find や robocopy のように終了コードの意味が特殊なコマンドもあるため、0/非0 の二択ではなく「値の意味を前提にした分岐」を設計する必要があります。
ERRORLEVEL を「なんとなく見る」のではなく、どのコマンドの結果を見ているかを固定し、戻り値設計まで含めて組むことで、実運用に耐えるエラー判定になります。

