バッチファイルの条件分岐は自動化スクリプトの要です。「ファイルがあれば処理する」「エラーが起きたら中断する」「入力値によって処理を切り替える」など、実務で必ず使う場面が多くあります。
この記事では、if文の基本構文から、数値・文字列・ファイル存在・ERRORLEVEL・AND/OR条件・ループ内分岐まで、体系的に解説します。
- if 文の基本構文とカッコブロックの書き方
- 数値比較演算子(EQU / NEQ / GTR / GEQ / LSS / LEQ)の使い方
- 文字列比較・大文字小文字無視・defined による分岐
- ファイル・フォルダの存在チェック(if exist)
- ERRORLEVEL による成功・失敗の判定
- else if を使った多段分岐
- AND条件・OR条件の実現方法
- ループ内での条件分岐(遅延展開の必要性)
- 落とし穴5選・実践例3本・FAQ6問
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
if not exist "file.txt"(存在しない場合に真)、if not "%VAR%"=="abc"(一致しない場合に真)。not は if のどの条件にも付けられます。if "9" GTR "10"(文字列)は真になりますが、if 9 GTR 10(数値)は偽です。数値を比較するときは必ず算術演算子を使いましょう。setlocal enabledelayedexpansion と !VAR! が必要です。setlocal enabledelayedexpansion 完全ガイドを参照してください。" で囲み、特殊文字は ^ でエスケープします。例: if "%VAR%"=="a^&b"。文字列に ! が含まれる場合は遅延展開を有効にして !VAR! で扱います。else if の連鎖で同等の処理が書けます。値が多い場合は goto :%VAR% のようにラベルジャンプを使う方法もあります(例: goto :case_%MENU_NUM%)。フラグを使った方法は フラグを更新する方法を参照してください。
