「本当に削除しますか?(y/n)」「本番デプロイを続行しますか?」――バッチファイルで操作前に確認を挟むことで、誤操作による取り返しのつかないミスを防げます。
本記事では set /p による基本形から CHOICE コマンドを使ったよりシンプルな実装、デフォルト値・タイムアウト付きの応用パターンまで体系的に解説します。
目次
- 方法1:set /p で y/n を入力させる
- 方法2:CHOICE コマンドで y/n を選択させる
- 方法3:デフォルト値付き確認(Enter で自動承認)
- 方法4:タイムアウト付き自動承認(CHOICE /T)
- 方法比較表
- 実践例A:ファイル削除前の確認ダイアログ
- 実践例B:本番デプロイ前の複数確認
- 実践例C:タイムアウト付き自動処理
- 落とし穴5選
- FAQ
- まとめ
方法1:set /p で y/n を入力させる
set /p はプロンプトを表示してユーザーのキーボード入力を変数に格納するコマンドです。if /i と組み合わせて y/n を判定します。
@echo off
setlocal
:ask
set "INPUT="
set /p "INPUT=続行しますか? [y/n]: "
if /i "%INPUT%"=="y" (
echo はいを選択しました。処理を続行します。
goto :main
)
if /i "%INPUT%"=="n" (
echo いいえを選択しました。処理を中止します。
exit /b 0
)
echo y または n を入力してください。
goto :ask
:main
echo 処理を実行中...
endlocal
ポイント:
set "INPUT="で毎回変数を初期化する(空Enterでも前回値が残らないようにする)/iフラグで大文字・小文字を区別しない(Y と y を同等に扱う)- 想定外の入力は
goto :askでループして再入力を促す
方法2:CHOICE コマンドで y/n を選択させる
CHOICE はキーを1つ押すだけで選択できる専用コマンドです。Enterが不要なため操作が直感的で、結果は ERRORLEVEL で取得します。
@echo off
setlocal
choice /c YN /m "続行しますか"
if ERRORLEVEL 2 (
echo いいえを選択しました。処理を中止します。
exit /b 0
)
if ERRORLEVEL 1 (
echo はいを選択しました。処理を続行します。
)
echo 処理を実行中...
endlocal
CHOICE の ERRORLEVEL は選択肢の順番に対応します。/c YN の場合:
| キー | ERRORLEVEL |
|---|---|
| Y | 1 |
| N | 2 |
重要: if ERRORLEVEL N は「N 以上なら真」という意味のため、大きい値から順に判定してください。N→Y の順(降順)で if ERRORLEVEL を書くのが正しいパターンです。
CHOICE コマンドの主なオプション
| オプション | 意味 | 例 |
|---|---|---|
/c キー一覧 |
受け付けるキーを指定 | /c YN |
/m メッセージ |
プロンプト文字列 | /m "続行しますか" |
/d キー |
タイムアウト時のデフォルト | /d Y |
/t 秒数 |
自動選択までの待機秒数 | /t 10 |
/n |
キー一覧を表示しない | /n |
方法3:デフォルト値付き確認(Enter で自動承認)
set /p でEnterのみ入力された場合にデフォルト値を適用するパターンです。「[Y/n]」のように大文字で示したキーがデフォルトであることを視覚的に伝えます。
@echo off
setlocal
:: デフォルト=Y(Enterだけ押した場合にYとして扱う)
set "INPUT=Y"
set /p "INPUT=続行しますか? [Y/n]: "
if /i "%INPUT%"=="n" (
echo キャンセルしました。
exit /b 0
)
echo 続行します。処理を実行中...
endlocal
set "INPUT=Y" で先にデフォルト値を設定しておくと、空Enter時も Y が入ったままになります。n が入力された場合だけキャンセル処理を行えばOKです。
方法4:タイムアウト付き自動承認(CHOICE /T)
一定時間内に回答がなければデフォルト値で自動選択するパターンです。自動化スクリプトで人が監視しているときは確認を挟みつつ、無人実行時は自動承認させたい場合に有効です。
@echo off
setlocal
echo 10秒以内に回答がない場合、自動的に Y が選択されます。
choice /c YN /m "続行しますか" /t 10 /d Y
if ERRORLEVEL 2 (
echo いいえを選択しました。処理を中止します。
exit /b 0
)
if ERRORLEVEL 1 (
echo はい(またはタイムアウト)を選択しました。処理を続行します。
)
echo 処理を実行中...
endlocal
タスクスケジューラや無人バッチでもタイムアウト後に自動続行するため、ハングアップしません。
方法比較表
| 方法 | 入力方法 | デフォルト値 | タイムアウト | 主な用途 |
|---|---|---|---|---|
| set /p | 文字列+Enter | ○(変数初期値で設定) | × | 柔軟な入力・複数文字対応 |
| CHOICE | キー1つのみ | ○(/d オプション) | ○(/t オプション) | シンプルなy/n・自動化 |
インタラクティブ性と確実性を求めるなら CHOICE が推奨です。複数文字の入力や日本語プロンプトが必要な場合は set /p を使います。
実践例A:ファイル削除前の確認ダイアログ
重要なファイルを削除する前に確認を挟む定番パターンです。誤操作によるデータ消失を防ぎます。
@echo off
setlocal
set TARGET=C:\Logs\old_data
if not exist "%TARGET%" (
echo [INFO] 削除対象が見つかりません: %TARGET%
exit /b 0
)
echo 以下を削除します:
echo %TARGET%
echo.
choice /c YN /m "本当に削除しますか"
if ERRORLEVEL 2 (
echo キャンセルしました。
exit /b 0
)
if ERRORLEVEL 1 (
echo 削除中...
if exist "%TARGET%\*" (
rd /s /q "%TARGET%"
) else (
del /f /q "%TARGET%"
)
echo 削除完了。
)
endlocal
削除前にパスを表示して視認できるようにしています。フォルダの場合は rd /s /q、ファイルの場合は del /f /q で処理を切り替えています。
実践例B:本番デプロイ前の複数確認
本番環境へのデプロイ前に複数の確認を順番に行い、全てYでないと処理が進まないパターンです。
@echo off
setlocal
echo ========================================
echo 本番デプロイ確認
echo ========================================
echo.
:: 確認1: バックアップ済みか
choice /c YN /m "[1/3] バックアップは完了していますか"
if ERRORLEVEL 2 (
echo バックアップを先に実施してください。中止します。
exit /b 1
)
:: 確認2: テスト済みか
choice /c YN /m "[2/3] テスト環境での確認は完了していますか"
if ERRORLEVEL 2 (
echo テスト確認後に再実行してください。中止します。
exit /b 1
)
:: 確認3: 最終確認
choice /c YN /m "[3/3] 本番環境へのデプロイを実行しますか"
if ERRORLEVEL 2 (
echo デプロイを中止しました。
exit /b 0
)
echo.
echo すべての確認が完了しました。デプロイを開始します。
echo [%date% %time%] デプロイ開始
echo 処理中...
endlocal
各確認で N を選んだ場合に即座に処理を中止し、適切なメッセージを表示します。exit /b の使い方と組み合わせることで、サブルーチン内から正しく終了できます。
実践例C:タイムアウト付き自動処理
定期実行スクリプトで、人が監視しているときは確認を挟み、無人実行時(タスクスケジューラ等)では自動続行するパターンです。
@echo off
setlocal
set LOG=C:\Logs\auto-task.log
echo [%date% %time%] スクリプト開始 >> %LOG%
:: インタラクティブ実行かどうか判定(引数 /auto が渡された場合は確認スキップ)
if /i "%1"=="/auto" (
echo [AUTO] 自動実行モード。確認をスキップします。
goto :do_task
)
:: 10秒待機・デフォルトY
echo 処理を開始します。キャンセルする場合は N を押してください。
choice /c YN /m "10秒後に自動的に開始します" /t 10 /d Y
if ERRORLEVEL 2 (
echo キャンセルしました。
echo [%date% %time%] キャンセル >> %LOG%
exit /b 0
)
:do_task
echo 処理を実行中...
echo [%date% %time%] 処理実行 >> %LOG%
echo 完了。
echo [%date% %time%] 完了 >> %LOG%
endlocal
cleanup.bat /auto で実行すると確認ダイアログをスキップして自動実行、引数なしで実行すると10秒のカウントダウン付きで確認します。
落とし穴5選
落とし穴1:set /p で変数を初期化しないと空Enter時に前回値が残る
set /p で変数を初期化せずに使うと、ユーザーがEnterだけ押した場合に変数の値が更新されず、前回の入力値がそのまま残ります。ループ内では毎回 set "INPUT=" で必ずリセットしてください。
:: NG: INPUT が前回値のまま残る :ask set /p "INPUT=続行しますか? [y/n]: " :: OK: 毎回リセット :ask set "INPUT=" set /p "INPUT=続行しますか? [y/n]: "
落とし穴2:/i フラグを忘れると大文字 Y/N が受け付けられない
if "%INPUT%"=="y"(/i なし)では小文字の y のみ一致します。ユーザーが大文字 Y を入力した場合に else に落ちてしまいます。if /i を必ず付けてください。
:: NG: "Y" を入力されると else に落ちる if "%INPUT%"=="y" (echo はい) else (echo いいえ) :: OK: 大文字・小文字どちらも受け付ける if /i "%INPUT%"=="y" (echo はい) else (echo いいえ)
落とし穴3:CHOICE の ERRORLEVEL は降順で判定する
if ERRORLEVEL N は「N 以上なら真」という意味です。昇順(1→2)で書くと、ERRORLEVEL=2 のときに if ERRORLEVEL 1 も真になり誤動作します。必ず大きい値(2)から先に判定してください。
:: NG: 昇順で書くと ERRORLEVEL=2 でも最初の if が真になる if ERRORLEVEL 1 echo Y が選ばれました if ERRORLEVEL 2 echo N が選ばれました :: OK: 降順(大きい値から)で判定 if ERRORLEVEL 2 echo N が選ばれました if ERRORLEVEL 1 echo Y が選ばれました
落とし穴4:CHOICE はリダイレクトやパイプ経由では動かない
choice はコンソールに直接接続されているときのみ動作します。choice < input.txt のようにリダイレクトで入力を渡すことはできません。自動テストや入力ファイルを使う場合は set /p を使ってください。
落とし穴5:set /p でクォートなし変数を使うと空文字でエラー
変数参照を %INPUT%(クォートなし)で使うと、変数が空の場合に if ==y となり構文エラーになります。常に "%INPUT%" のようにクォートで囲んでください。
:: NG: INPUT が空のとき「if ==y」になり構文エラー if %INPUT%==y echo はい :: OK: クォートで囲む if "%INPUT%"=="y" echo はい
FAQ
CHOICE /c ABC のように複数キーを指定できます。ERRORLEVEL は A=1, B=2, C=3 に対応します。set /p を使えば任意の文字列入力も受け付けられます。chcp 932(Shift-JIS)または chcp 65001(UTF-8)をスクリプト冒頭に追加してください。ただしchcp 65001は一部環境で問題が出ることがあります。echo [%date% %time%] 確認: %INPUT% >> log.txt のように確認後にログ出力を追加します。CHOICEの場合はERRORLEVELを変数に保存してからログに記録してください。CHOICE の後 ERRORLEVEL を参照する前に別のコマンドを実行すると値が上書きされます。ERRORLEVEL を変数に退避してから判定してください。set /a RESULT=%ERRORLEVEL% のように保存します。CHOICE /t 0 /d Y(待機0秒・デフォルトY)でタイムアウトを0に設定する方法が使えます。まとめ
| 状況 | 推奨方法 |
|---|---|
| シンプルにy/nだけ確認したい | CHOICE /c YN |
| タイムアウト・デフォルト値が必要 | CHOICE /t /d |
| Enter で続行・n でキャンセルしたい | set /p(デフォルト値付き) |
| 自動実行と対話実行を切り替えたい | 引数判定 + CHOICE /t |
| 3択以上の選択が必要 | CHOICE /c ABC… |
遅延展開変数を使ったループ内での判定についてはsetlocal enabledelayedexpansion 完全ガイドも参照してください。

