【bat】バッチファイルで条件分岐する方法完全ガイド|if文・数値比較・文字列比較・ERRORLEVEL・AND/OR・実践パターンまで

バッチファイルの条件分岐は自動化スクリプトの要です。「ファイルがあれば処理する」「エラーが起きたら中断する」「入力値によって処理を切り替える」など、実務で必ず使う場面が多くあります。

この記事では、if文の基本構文から、数値・文字列・ファイル存在・ERRORLEVEL・AND/OR条件・ループ内分岐まで、体系的に解説します。

この記事でわかること

  • if 文の基本構文とカッコブロックの書き方
  • 数値比較演算子(EQU / NEQ / GTR / GEQ / LSS / LEQ)の使い方
  • 文字列比較・大文字小文字無視・defined による分岐
  • ファイル・フォルダの存在チェック(if exist)
  • ERRORLEVEL による成功・失敗の判定
  • else if を使った多段分岐
  • AND条件・OR条件の実現方法
  • ループ内での条件分岐(遅延展開の必要性)
  • 落とし穴5選・実践例3本・FAQ6問
スポンサーリンク
  1. 1. if 文の基本構文
    1. 条件の種類一覧
  2. 2. 数値比較による条件分岐
    1. 比較演算子一覧
    2. 基本例:入力値の範囲チェック
  3. 3. 文字列比較による条件分岐
    1. 3-1. 基本の文字列比較(==)
    2. 3-2. 大文字小文字を無視して比較(/i)
    3. 3-3. 変数の定義・未定義チェック(defined)
  4. 4. ファイル・フォルダの存在チェック(if exist)
    1. 4-1. ファイルの存在確認
    2. 4-2. フォルダの存在確認
    3. 4-3. ワイルドカードで複数ファイルの存在確認
  5. 5. ERRORLEVEL による条件分岐
    1. 5-1. errorlevel の判定方法(2種類)
    2. 5-2. ERRORLEVEL の詳細分岐
  6. 6. else if を使った多段分岐
  7. 7. AND条件・OR条件の表現
    1. 7-1. AND条件:if のネスト
    2. 7-2. OR条件:フラグ変数を使う
    3. 7-3. コマンドの成否による連続実行(&& と ||)
  8. 8. ループ内での条件分岐(遅延展開)
    1. NG例:%VAR% では古い値が取れる
    2. OK例:!VAR! で最新値を参照
  9. 9. 落とし穴5選と対策
    1. 落とし穴1:変数を ” で囲まないと空のとき構文エラー
    2. 落とし穴2:( の位置が違うと構文エラー
    3. 落とし穴3:else の前後の ) ( を別行にできない
    4. 落とし穴4:文字列比較で == の両側に余分なスペースが入る
    5. 落とし穴5:if errorlevel N は「N 以上」を意味する
  10. 10. 実践例3本
    1. 実践例1:引数のバリデーションと処理分岐
    2. 実践例2:ファイル処理の前後条件チェック
    3. 実践例3:y/n 確認プロンプトと処理分岐
  11. 11. まとめ
  12. FAQ

1. if 文の基本構文

バッチファイルの if 文の基本形は次のとおりです。

:: 1行形式(単純な処理)
if 条件 コマンド

:: ブロック形式(複数コマンドを実行)
if 条件 (
    コマンド1
    コマンド2
) else (
    コマンド3
    コマンド4
)

条件が成り立つときは then 相当のブロックが、成り立たないときは else ブロックが実行されます。

書き方のルール:(if 条件 と同じ行に書かなければなりません。改行して ( を書くと構文エラーになります。

条件の種類一覧

条件の種類 構文例 説明
数値比較 if %N% EQU 0 数値の大小・等値を比較
文字列比較 if "%STR%"=="abc" 文字列の一致を比較
ファイル存在 if exist "file.txt" ファイル・フォルダの存在確認
ERRORLEVEL if errorlevel 1 直前コマンドの終了コード判定
変数未定義 if not defined VAR 変数が未定義かを確認

2. 数値比較による条件分岐

数値を比較するには算術比較演算子を使います。数値を比較する方法の完全ガイドも参照してください。

比較演算子一覧

演算子 意味
EQU 等しい(Equal) if %N% EQU 0
NEQ 等しくない(Not Equal) if %N% NEQ 0
GTR より大きい(Greater Than) if %N% GTR 10
GEQ 以上(Greater or Equal) if %N% GEQ 10
LSS より小さい(Less Than) if %N% LSS 10
LEQ 以下(Less or Equal) if %N% LEQ 10

基本例:入力値の範囲チェック

@echo off
setlocal

set /p NUM=数値を入力してください: 

if %NUM% LSS 0 (
    echo 負の数です
) else if %NUM% EQU 0 (
    echo ゼロです
) else if %NUM% LEQ 100 (
    echo 1 〜 100 の範囲内です
) else (
    echo 100 より大きい数です
)
注意:バッチの数値比較は整数のみ対応です。小数点は文字列として扱われ正しく比較できません。

3. 文字列比較による条件分岐

文字列の一致・不一致・大文字小文字無視・定義チェックを使い分けます。文字列を比較する方法も参照してください。

3-1. 基本の文字列比較(==)

@echo off
setlocal

set "ENV=production"

if "%ENV%"=="production" (
    echo 本番環境です。慎重に操作してください。
) else if "%ENV%"=="staging" (
    echo ステージング環境です。
) else (
    echo 開発環境です。
)

%VAR%" で囲む理由:変数が未定義や空のとき == "" の形になり構文エラーを防ぎます。

3-2. 大文字小文字を無視して比較(/i)

@echo off
setlocal

set "INPUT=YES"

:: /i を付けると Yes・yes・YES すべてに一致
if /i "%INPUT%"=="yes" (
    echo Yes と入力されました
) else (
    echo Yes 以外が入力されました
)

3-3. 変数の定義・未定義チェック(defined)

@echo off
setlocal

:: 引数が渡されているかを確認(位置引数は defined では確認できないため "%~1" を使う)
if "%~1"=="" (
    echo 使い方: %~nx0 ファイル名
    exit /b 1
)

:: 環境変数の定義チェック
if not defined MY_CONFIG (
    echo [WARN] MY_CONFIG が未設定です。デフォルト値を使用します。
    set "MY_CONFIG=default.cfg"
)
echo 設定ファイル: %MY_CONFIG%

環境変数を設定・参照する方法も合わせて確認してください。

4. ファイル・フォルダの存在チェック(if exist)

ファイルやフォルダの存在を確認して処理を分岐します。IF EXISTでファイル・フォルダの存在確認をする方法も参照してください。

4-1. ファイルの存在確認

@echo off
setlocal

set "TARGET=C:\work\data.csv"

if exist "%TARGET%" (
    echo ファイルが見つかりました: %TARGET%
    type "%TARGET%"
) else (
    echo [ERROR] ファイルが見つかりません: %TARGET%
    exit /b 1
)

4-2. フォルダの存在確認

@echo off
setlocal

set "DIR=C:\work\output"

:: フォルダが存在しなければ作成する
if not exist "%DIR%\" (
    echo フォルダを作成します: %DIR%
    mkdir "%DIR%"
)

:: フォルダが存在することを確認して処理
if exist "%DIR%\" (
    echo 出力先フォルダ準備完了
    copy "C:\src\*" "%DIR%\" >nul
)

フォルダの存在確認には末尾に \ を付けます("%DIR%\")。これでファイルとフォルダを区別できます。

4-3. ワイルドカードで複数ファイルの存在確認

@echo off
setlocal

:: *.csv ファイルが1件以上存在するか確認
if exist "C:\work\*.csv" (
    echo CSVファイルが存在します。処理を開始します。
) else (
    echo CSVファイルがありません。処理をスキップします。
)

5. ERRORLEVEL による条件分岐

コマンドの成功・失敗を ERRORLEVEL で判定します。ERRORLEVELを使ったエラーハンドリングも参照してください。

5-1. errorlevel の判定方法(2種類)

@echo off
setlocal

xcopy /y "C:\src\*" "D:\dst\" >nul 2>&1

:: 方法1: if errorlevel N(N以上なら真)
if errorlevel 1 (
    echo [ERROR] xcopy 失敗(errorlevel 1 以上)
    exit /b 1
)

:: 方法2: %ERRORLEVEL% を数値比較(厳密に == で判定)
if %ERRORLEVEL% EQU 0 (
    echo [OK] xcopy 成功
)

5-2. ERRORLEVEL の詳細分岐

@echo off
setlocal

robocopy "C:\src" "D:\dst" /e >nul 2>&1
set "RC=%ERRORLEVEL%"

:: robocopy は終了コードにビットフラグを使う
if %RC% GEQ 8 (
    echo [ERROR] コピー失敗: エラーコード %RC%
    exit /b 1
) else if %RC% GEQ 4 (
    echo [WARN] 一部ミスマッチあり: コード %RC%
) else (
    echo [OK] コピー成功: コード %RC%
)
注意:if errorlevel N は「ERRORLEVELが N 以上」を意味します。厳密に「N のみ」を判定したい場合は if %ERRORLEVEL% EQU N を使ってください。

6. else if を使った多段分岐

3つ以上の条件を順番に評価する多段分岐です。

@echo off
setlocal

set /p SCORE=スコアを入力: 

if %SCORE% GEQ 90 (
    echo 評価: A(優秀)
) else if %SCORE% GEQ 70 (
    echo 評価: B(良好)
) else if %SCORE% GEQ 50 (
    echo 評価: C(合格)
) else (
    echo 評価: D(不合格)
)

else if は実際には else ( if ... ) の省略形です。深くネストしてもCMDは正しく解釈します。

7. AND条件・OR条件の表現

バッチには &&(AND)や ||(OR)のような論理演算子がありませんが、ネストした if やフラグ変数で表現できます。AND条件を使う方法OR条件を使う方法も参照してください。

7-1. AND条件:if のネスト

@echo off
setlocal

set "FILE=C:\work\data.csv"
set "FLAG=1"

:: ファイルが存在 かつ FLAG が 1 の場合のみ処理
if exist "%FILE%" (
    if "%FLAG%"=="1" (
        echo AND条件が成立しました
        type "%FILE%"
    )
)

7-2. OR条件:フラグ変数を使う

@echo off
setlocal

set "FILE_A=C:\work\a.csv"
set "FILE_B=C:\work\b.csv"
set "FOUND=0"

:: a.csv または b.csv が存在すれば処理
if exist "%FILE_A%" set "FOUND=1"
if exist "%FILE_B%" set "FOUND=1"

if "%FOUND%"=="1" (
    echo 対象ファイルが見つかりました
) else (
    echo 対象ファイルが見つかりません
)

7-3. コマンドの成否による連続実行(&& と ||)

@echo off
setlocal

:: コマンドが成功した場合のみ次を実行(&&)
mkdir "C:\work\output" && echo フォルダを作成しました

:: コマンドが失敗した場合のみ次を実行(||)
copy "C:\src\data.csv" "D:\dst\" || echo [ERROR] コピーに失敗しました

:: 組み合わせ:成功時とエラー時の処理を1行で書く
xcopy /y "C:\src" "D:\dst" >nul && echo OK || echo FAIL

8. ループ内での条件分岐(遅延展開)

for ループや if ブロック内で変数を更新してすぐ参照する場合、setlocal enabledelayedexpansion!VAR! が必要です。

詳細は setlocal enabledelayedexpansion 完全ガイドを参照してください。

NG例:%VAR% では古い値が取れる

@echo off
setlocal

set "STATUS=OK"

for %%F in (*.log) do (
    :: エラーがあれば STATUS を変更
    findstr /i "error" "%%F" >nul && set "STATUS=NG"
    :: NG: %STATUS% はループ開始時の値(常に OK)
    if "%STATUS%"=="NG" echo %%F にエラーあり
)

OK例:!VAR! で最新値を参照

@echo off
setlocal enabledelayedexpansion

set "STATUS=OK"

for %%F in (*.log) do (
    findstr /i "error" "%%F" >nul && set "STATUS=NG"
    :: OK: !STATUS! でループ内の最新値を参照
    if "!STATUS!"=="NG" (
        echo %%F にエラーがあります
        set "STATUS=OK"
    )
)

変数展開が思った通りに動かない原因と修正方法も参照してください。

9. 落とし穴5選と対策

落とし穴1:変数を ” で囲まないと空のとき構文エラー

:: NG: VAR が空または未定義の場合、if ==0 となって構文エラー
if %VAR%==0 echo ゼロ

:: OK: 必ず " で囲む
if "%VAR%"=="0" echo ゼロ

:: OK: defined で先に確認してから比較
if defined VAR (
    if "%VAR%"=="0" echo ゼロ
)

落とし穴2:( の位置が違うと構文エラー

:: NG: ( を次の行に書くと構文エラー
if "%X%"=="1"
(
    echo NG
)

:: OK: ( は if 条件と同じ行に書く
if "%X%"=="1" (
    echo OK
)

落とし穴3:else の前後の ) ( を別行にできない

:: NG: ) と else を別行に書いても動くが、環境により誤動作することがある
:: 意図しないコメント「:: 」が ) と同じ行に入ると即クラッシュ
if "%X%"=="1" (
    echo true
) :: このコメントはNG!バッチがクラッシュする
else (
    echo false
)

:: OK: ) else ( を1行にまとめる
if "%X%"=="1" (
    echo true
) else (
    echo false
)

落とし穴4:文字列比較で == の両側に余分なスペースが入る

:: NG: == の両側にスペースを入れると "apple " == "apple" となり不一致
if "%VAR%" == "apple" echo 一致

:: OK: スペースなしで書く
if "%VAR%"=="apple" echo 一致

落とし穴5:if errorlevel N は「N 以上」を意味する

:: NG: if errorlevel 0 は errorlevel が 0 以上なら真 → 常に真になる
if errorlevel 0 echo 成功  :: 常に実行される!

:: OK: 成功(0)を判定したいなら %ERRORLEVEL% EQU 0 を使う
if %ERRORLEVEL% EQU 0 echo 成功

:: OK: 失敗(1以上)を判定するなら if errorlevel 1 が正しい
if errorlevel 1 echo エラーが発生しました

10. 実践例3本

実践例1:引数のバリデーションと処理分岐

@echo off
setlocal

:: 引数チェック
if "%~1"=="" (
    echo 使い方: %~nx0 [env] [file]
    echo   env : production / staging / development
    echo   file: 処理対象のCSVファイルパス
    exit /b 1
)
if "%~2"=="" (
    echo [ERROR] ファイルパスを指定してください
    exit /b 1
)

set "ENV=%~1"
set "FILE=%~2"

:: 環境チェック
if /i not "%ENV%"=="production" if /i not "%ENV%"=="staging" if /i not "%ENV%"=="development" (
    echo [ERROR] env は production / staging / development のいずれかを指定してください
    exit /b 1
)

:: ファイル存在チェック
if not exist "%FILE%" (
    echo [ERROR] ファイルが見つかりません: %FILE%
    exit /b 1
)

:: 環境別処理
if /i "%ENV%"=="production" (
    echo [本番] %FILE% を処理します
    call :process_prod "%FILE%"
) else if /i "%ENV%"=="staging" (
    echo [ステージング] %FILE% を処理します
    call :process_staging "%FILE%"
) else (
    echo [開発] %FILE% を処理します
    call :process_dev "%FILE%"
)
exit /b 0

:process_prod
echo 本番処理: %~1
exit /b 0
:process_staging
echo ステージング処理: %~1
exit /b 0
:process_dev
echo 開発処理: %~1
exit /b 0

サブルーチンへの分岐については サブルーチン完全ガイドも参照してください。

実践例2:ファイル処理の前後条件チェック

@echo off
setlocal enabledelayedexpansion

set "SRC_DIR=C:\data\input"
set "DST_DIR=C:\data\output"
set "LOG=C:\data\process.log"
set "ERR_CNT=0"

:: 事前チェック
if not exist "%SRC_DIR%\" (
    echo [ERROR] 入力フォルダが見つかりません: %SRC_DIR%
    exit /b 1
)
if not exist "%DST_DIR%\" mkdir "%DST_DIR%"

:: CSVファイルが存在するか確認
if not exist "%SRC_DIR%\*.csv" (
    echo [INFO] 処理対象のCSVファイルがありません
    exit /b 0
)

:: ファイル処理ループ
for %%F in ("%SRC_DIR%\*.csv") do (
    echo 処理中: %%~nxF
    copy "%%F" "%DST_DIR%\" >nul 2>&1
    if !errorlevel! NEQ 0 (
        echo [ERROR] %%~nxF のコピー失敗 >> "%LOG%"
        set /a ERR_CNT+=1
    ) else (
        echo [OK] %%~nxF >> "%LOG%"
    )
)

:: 最終結果の判定
if !ERR_CNT! GTR 0 (
    echo [WARN] %ERR_CNT% 件のエラーがありました。ログ: %LOG%
    exit /b 1
) else (
    echo [OK] 全ファイル処理完了
)

実践例3:y/n 確認プロンプトと処理分岐

@echo off
setlocal

set "TARGET_DIR=C:\work\output"

echo 対象フォルダを削除します: %TARGET_DIR%
set /p CONFIRM=本当に削除しますか? (y/n): 

if /i "%CONFIRM%"=="y" (
    if exist "%TARGET_DIR%\" (
        rd /s /q "%TARGET_DIR%"
        if errorlevel 1 (
            echo [ERROR] 削除に失敗しました
            exit /b 1
        )
        echo [OK] 削除完了: %TARGET_DIR%
    ) else (
        echo [INFO] フォルダが存在しません: %TARGET_DIR%
    )
) else if /i "%CONFIRM%"=="n" (
    echo キャンセルしました
    exit /b 0
) else (
    echo [ERROR] y または n を入力してください
    exit /b 1
)

y/n 確認の詳細なパターンは y/n確認による処理分岐の完全ガイドを参照してください。

11. まとめ

バッチファイルの条件分岐まとめです。

場面 使う構文
数値の大小比較 if %N% EQU/GTR/LSS 値
文字列の一致確認 if "%STR%"=="値"
大文字小文字を無視して比較 if /i "%STR%"=="値"
変数が定義されているか確認 if defined VAR
ファイル・フォルダの存在確認 if exist "パス"
コマンドの成否判定 if errorlevel 1 / if %ERRORLEVEL% EQU 0
AND条件 if ネスト
OR条件 フラグ変数 + if
ループ内での変数参照 setlocal enabledelayedexpansion + !VAR!

FAQ

Q. if の条件に not を付けるとどうなりますか?
A. 条件を否定できます。例: if not exist "file.txt"(存在しない場合に真)、if not "%VAR%"=="abc"(一致しない場合に真)。not は if のどの条件にも付けられます。
Q. else if は何段でもネストできますか?
A. 原則として何段でも書けます。ただし深くなるほど可読性が下がるため、5段以上になる場合はサブルーチン(CALL・GOTO)やフラグ変数で整理するとよいでしょう。
Q. 数値比較と文字列比較(==)の違いは何ですか?
A. 数値比較(EQU/GTR/LSS など)は算術的に数値として比較します。文字列比較(==)は文字列として辞書順で比較します。たとえば if "9" GTR "10"(文字列)は真になりますが、if 9 GTR 10(数値)は偽です。数値を比較するときは必ず算術演算子を使いましょう。
Q. for ループ内で if を使うと変数の値が更新されません。
A. ループや if ブロック内で変数を更新して同ブロック内で参照するには setlocal enabledelayedexpansion!VAR! が必要です。setlocal enabledelayedexpansion 完全ガイドを参照してください。
Q. if 文の条件に特殊文字(&や^など)が含まれると動きません。
A. 変数を " で囲み、特殊文字は ^ でエスケープします。例: if "%VAR%"=="a^&b"。文字列に ! が含まれる場合は遅延展開を有効にして !VAR! で扱います。
Q. バッチで switch 文のように多分岐を書きたい。
A. バッチに switch はありませんが、else if の連鎖で同等の処理が書けます。値が多い場合は goto :%VAR% のようにラベルジャンプを使う方法もあります(例: goto :case_%MENU_NUM%)。フラグを使った方法は フラグを更新する方法を参照してください。