バッチファイル(bat)でユーザーに入力を求めたいとき、set /p コマンド1行で対話型スクリプトが作れます。本記事では基本的な文字列入力から、空入力チェック・デフォルト値・Y/N 確認(choice)・数値バリデーション・メニュー選択まで、実務で使える入力パターンを体系的に解説します。
この記事でできること
set /pでプロンプトを表示してユーザーの入力を変数に保存- 空入力チェック・デフォルト値の設定
choiceで Y/N や複数選択肢をキー1つで受け取る- 数値入力のバリデーション(範囲チェック)
- GOTO + ラベルを使ったメニュー選択の実装
- 実践例3本(削除確認・ファイル名入力処理・設定ウィザード)と落とし穴・FAQ も解説
入力方法の比較
bat で入力を受け取る方法は主に2種類あります。用途に合わせて使い分けましょう。
| 方法 | コマンド | 用途 | 特徴 |
|---|---|---|---|
| 文字列・数値入力 | set /p |
名前・パス・数値など自由入力 | Enter で確定。入力内容は変数に保存 |
| 1キー選択 | choice |
Y/N・メニュー番号など限定入力 | Enter 不要。ERRORLEVEL で結果取得 |
set /p は入力内容をそのまま変数に代入します。空入力・予期しない文字・パス区切り文字なども混入しうるため、重要な処理の前には必ずバリデーション(後述)を入れましょう。
方法1: set /p で文字列を入力
set /p 変数名=プロンプト文字列 がフォーマットです。Enter を押すまでの入力内容が変数に保存されます。
基本: 名前を入力して挨拶
@echo off setlocal set /p NAME=お名前を入力してください: echo こんにちは、%NAME% さん! pause endlocal
複数の値を順番に入力
複数の set /p を並べることで、ウィザード形式で順番に入力を求めることができます。
@echo off setlocal set /p FIRST=姓を入力: set /p LAST=名を入力: set /p AGE=年齢を入力: echo ======================== echo 姓名: %FIRST% %LAST% echo 年齢: %AGE% 歳 echo ======================== pause endlocal
ポイント: プロンプト文字列末尾の半角スペースは意図的なものです。スペースを入れないとカーソルが直後に来て入力しづらくなります。
方法2: 空入力チェック・デフォルト値の設定
Enter だけを押した場合、変数は空文字列(または前回の値)になります。空入力を検出して処理を分岐したり、デフォルト値を設定しましょう。
空入力チェックと再入力ループ
@echo off
setlocal
:INPUT_LOOP
set "FILENAME="
set /p FILENAME=ファイル名を入力(必須):
if "%FILENAME%"=="" (
echo [エラー] ファイル名を入力してください。
goto INPUT_LOOP
)
echo 入力されたファイル名: %FILENAME%
endlocal
デフォルト値の設定
空入力のときに事前に決めた値(デフォルト)を使う方法です。プロンプトに [デフォルト値] を表示すると親切です。
@echo off setlocal rem デフォルト値を事前にセット set "TIMEOUT=30" set /p TIMEOUT=タイムアウト秒を入力 [デフォルト: 30]: rem 空入力ならデフォルト値を維持(set /p は空入力時に変数を変更しない) echo タイムアウト: %TIMEOUT% 秒 endlocal
set /p は Enter のみの空入力を受け取ったとき、変数の値を変更しません。そのため set /p の前にデフォルト値をセットしておくと、空入力でもデフォルト値が残る仕組みになります。
方法3: Y/N 確認には choice コマンド
choice コマンドは Enter 不要で1キーの選択入力を受け付けます。押したキーに応じて ERRORLEVEL がセットされるため、処理の分岐がシンプルに書けます。
Y/N で処理を分岐
@echo off
setlocal
echo 処理を実行しますか?
choice /c YN /m "実行する場合は Y、中止する場合は N を押してください"
rem ERRORLEVEL は選択肢の左から順に 1, 2, 3...
rem Y=1, N=2
if errorlevel 2 (
echo 処理を中止しました。
goto END
)
if errorlevel 1 (
echo 処理を実行します...
rem ここに実処理を記述
)
:END
endlocal
3択以上の選択肢
/c オプションに選択肢の文字を並べます。大文字小文字は区別されません(内部的に大文字に変換されます)。
@echo off
setlocal
echo バックアップ方式を選んでください:
echo 1. フルバックアップ
echo 2. 差分バックアップ
echo 3. キャンセル
choice /c 123 /m "番号を入力してください"
if errorlevel 3 echo キャンセルしました。& goto END
if errorlevel 2 echo 差分バックアップを開始します。& goto DIFF
if errorlevel 1 echo フルバックアップを開始します。& goto FULL
:FULL
rem フルバックアップ処理
goto END
:DIFF
rem 差分バックアップ処理
goto END
:END
endlocal
if errorlevel N は「ERRORLEVEL が N 以上」を意味します。複数の分岐がある場合は必ず大きい値から順に判定してください。小さい値から判定すると、より大きい値も最初の条件にマッチしてしまいます。
ERRORLEVEL の大きい値から降順で判定するルールは choice 以外のコマンドでも共通です。ファイル・フォルダの存在確認には bat の IF EXIST でファイル・フォルダの存在確認をする方法も合わせてご覧ください。
方法4: 数値入力のバリデーション
set /a を使うと入力値が数値かどうかを確認できます。数値でない場合 set /a はエラーを返します。範囲チェックと組み合わせて、安全な数値入力を実装しましょう。
数値チェック + 範囲バリデーション
@echo off
setlocal enabledelayedexpansion
:NUM_LOOP
set "NUM="
set /p NUM=1〜10 の数値を入力:
rem 空入力チェック
if "%NUM%"=="" (
echo [エラー] 数値を入力してください。
goto NUM_LOOP
)
rem 数値チェック(set /a は非数値を 0 に変換する)
rem 入力が "0" でなく CHECK が 0 なら非数値と判定
set /a CHECK=%NUM% 2>nul
if "%CHECK%"=="0" if not "%NUM%"=="0" (
echo [エラー] 数値以外が入力されました: %NUM%
goto NUM_LOOP
)
rem 小数・負数は別途チェック
echo %NUM% | findstr /r "^-" >nul
if not errorlevel 1 (
echo [エラー] 正の整数を入力してください。
goto NUM_LOOP
)
rem 範囲チェック
if %NUM% LSS 1 (
echo [エラー] 1 以上の値を入力してください。
goto NUM_LOOP
)
if %NUM% GTR 10 (
echo [エラー] 10 以下の値を入力してください。
goto NUM_LOOP
)
echo 入力値: %NUM%
endlocal
bat での変数操作の詳しい使い方は bat の setlocal enabledelayedexpansion 完全ガイドも合わせて参照してください。
方法5: GOTO とラベルでメニュー選択
番号を入力させてメニュー項目に GOTO で飛ぶ方法です。choice では対応できない多項目・複雑な分岐に使います。
@echo off
setlocal
:MENU
cls
echo =============================
echo メインメニュー
echo =============================
echo 1. ファイルを処理する
echo 2. バックアップを実行する
echo 3. 設定を変更する
echo 0. 終了
echo =============================
set /p CHOICE=番号を入力してください:
if "%CHOICE%"=="1" goto PROCESS
if "%CHOICE%"=="2" goto BACKUP
if "%CHOICE%"=="3" goto CONFIG
if "%CHOICE%"=="0" goto EXIT_MENU
echo [エラー] 0〜3 の番号を入力してください。
pause
goto MENU
:PROCESS
echo ファイル処理を実行します...
pause
goto MENU
:BACKUP
echo バックアップを実行します...
pause
goto MENU
:CONFIG
echo 設定変更画面(未実装)
pause
goto MENU
:EXIT_MENU
echo 終了します。
endlocal
ラベルと GOTO の詳しい使い方は bat のラベル・GOTO・CALL 完全ガイドを参照してください。
実践例A: ファイル削除の確認プロンプト
削除など取り消せない操作の前に Y/N 確認を挟み、誤操作を防ぐパターンです。
@echo off
setlocal
set "TARGET=C:\work\old_logs"
echo 以下のフォルダ内のファイルをすべて削除します。
echo 対象: %TARGET%
echo.
choice /c YN /m "本当に削除しますか?(Y=削除 / N=キャンセル)"
if errorlevel 2 (
echo キャンセルしました。
goto END
)
rem Y が選ばれた場合のみ削除実行
if exist "%TARGET%" (
del /q "%TARGET%\*"
echo 削除完了: %TARGET%
) else (
echo [INFO] 対象フォルダが存在しません: %TARGET%
)
:END
pause
endlocal
実践例B: ファイル名を入力して処理(存在チェック付き)
ユーザーにファイル名を入力させ、存在確認・バリデーションを経て処理するパターンです。
@echo off
setlocal
set "BASE_DIR=C:\data"
:ASK_FILE
set "FNAME="
set /p FNAME=処理するファイル名を入力(例: report.csv):
if "%FNAME%"=="" (
echo [エラー] ファイル名を入力してください。
goto ASK_FILE
)
rem Windowsのファイル名禁止文字チェック(\ / : < > | をグループ1、* ? " を個別に確認)
echo %FNAME% | findstr /r "[\\/:;<>|]" >nul
if not errorlevel 1 ( echo [エラー] ファイル名に使えない文字が含まれています。& goto ASK_FILE )
rem * ? " は findstr 正規表現での扱いが不安定なため個別チェック
echo %FNAME% | findstr /l "*" >nul
if not errorlevel 1 ( echo [エラー] * は使えません。& goto ASK_FILE )
echo %FNAME% | findstr /l "?" >nul
if not errorlevel 1 ( echo [エラー] ? は使えません。& goto ASK_FILE )
echo %FNAME% | findstr /l """" >nul
if not errorlevel 1 ( echo [エラー] " は使えません。& goto ASK_FILE )
rem ファイルの存在確認
if not exist "%BASE_DIR%\%FNAME%" (
echo [エラー] ファイルが見つかりません: %BASE_DIR%\%FNAME%
goto ASK_FILE
)
echo 処理対象: %BASE_DIR%\%FNAME%
rem ここに実処理を記述
echo 処理完了。
endlocal
実践例C: 複数入力の設定ウィザード
複数の設定値を順番に入力させ、最後にサマリーを表示して確認を取るウィザードパターンです。
@echo off
setlocal
echo =============================
echo バックアップ設定ウィザード
echo =============================
rem --- ソースフォルダ入力 ---
:ASK_SRC
set "SRC="
set /p SRC=バックアップ元フォルダを入力:
if "%SRC%"=="" ( echo 必須項目です。& goto ASK_SRC )
if not exist "%SRC%" ( echo フォルダが存在しません。& goto ASK_SRC )
rem --- 保存先フォルダ入力(デフォルト付き)---
set "DST=C:\backup"
set /p DST=保存先フォルダ [デフォルト: C:\backup]:
rem --- 世代数入力(デフォルト: 7)---
set "GEN=7"
set /p GEN=保存世代数 [デフォルト: 7]:
rem --- サマリー表示と最終確認 ---
echo.
echo =============================
echo 設定内容の確認
echo バックアップ元 : %SRC%
echo 保存先 : %DST%
echo 保存世代数 : %GEN%
echo =============================
choice /c YN /m "この設定で実行しますか?"
if errorlevel 2 (
echo キャンセルしました。
goto WIZARD_END
)
echo バックアップを開始します...
rem ここに実処理
:WIZARD_END
endlocal
よくある落とし穴
落とし穴1: 変数を初期化しないとゴミ値が残る
set /p は空入力を受け取ったとき変数の値を変えません。前回ループの値や実行前の環境変数が残ることがあります。set "VAR=" で必ず空にしてから set /p を呼んでください。
rem NG: 前回の値が残る可能性がある set /p NAME=名前: rem OK: 事前に空文字でリセット set "NAME=" set /p NAME=名前:
落とし穴2: プロンプト末尾のスペースが消える環境がある
set /p VAR=入力してください: の末尾スペースは一部の環境でスクリプトのエンコーディング次第で消えることがあります。スペースが表示されない場合はプロンプト文末に ^ を入れる回避策があります。
rem 末尾スペースが消える環境向けの回避策 set /p NAME=名前を入力してください: ^ rem または echo /p で別行にプロンプト表示 <nul set /p =[プロンプト] set /p NAME=
落とし穴3: パーセント記号(%)を含む入力がおかしくなる
ユーザーが %PATH% のようにパーセント記号を含む文字を入力すると、%PATH% がそのまま展開されて変数の値が壊れます。setlocal enabledelayedexpansion を使い !VAR! で参照するとこの問題を回避できます。
@echo off setlocal enabledelayedexpansion set "INPUT=" set /p INPUT=値を入力: rem %INPUT% だと % が展開されてしまうことがある rem !INPUT! を使うと安全 echo 入力値: !INPUT! endlocal
遅延展開の詳しい仕組みは bat の setlocal enabledelayedexpansion 完全ガイドを参照してください。
落とし穴4: choice コマンドの ERRORLEVEL 判定は降順で行う
if errorlevel N は「N 以上」を意味するため、昇順に並べると最初の条件に全ての値がマッチしてしまいます。
rem NG: 昇順判定(1以上の条件に 2, 3 も全部マッチする) choice /c 123 if errorlevel 1 echo 1が押されました (← 2,3も全部ここに入る) if errorlevel 2 echo 2が押されました (← 到達しない) rem OK: 降順判定 choice /c 123 if errorlevel 3 echo 3が押されました if errorlevel 2 echo 2が押されました if errorlevel 1 echo 1が押されました
落とし穴5: リダイレクトや | でパイプすると set /p が機能しない
script.bat < input.txt のようにリダイレクトで入力を与える場合、set /p はリダイレクトされたファイルから読み取ります。自動化テストでは便利ですが、対話型として使いたい場合は意図しない動作になります。また | でパイプすると set /p への入力が空になります。
rem 自動テスト用: echo で入力をリダイレクト echo TestUser| script.bat rem または script.bat < answers.txt rem answers.txt の内容(改行区切りで入力値を並べる) rem TestUser rem 25 rem Y
よくある質問(FAQ)
bat の set /p には入力を隠す機能がありません。PowerShell の Read-Host -AsSecureString を呼び出す方法が現実的です。
@echo off
setlocal
rem PowerShell 経由でパスワードを非表示入力
for /f "usebackq tokens=*" %%P in (`powershell -NoProfile -Command "$p = Read-Host -Prompt 'パスワード' -AsSecureString; [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($p))"`) do (
set "PASSWORD=%%P"
)
echo パスワードを受け取りました(表示しません)
endlocal
choice /t でタイムアウト秒数とデフォルト選択を指定できます。set /p にはタイムアウト機能がありません。
@echo off rem /t 10: 10秒後にデフォルト選択 /d N を自動選択 choice /c YN /t 10 /d N /m "処理を実行しますか?(10秒後に N に自動決定)" if errorlevel 2 echo キャンセル(または自動キャンセル) if errorlevel 1 echo 実行します
set /a で入力値をそのまま算術式に使えます。文字列が混じっていると 0 として扱われます。
@echo off setlocal set /p NUM1=1つ目の数値: set /p NUM2=2つ目の数値: set /a RESULT=%NUM1% + %NUM2% echo 合計: %RESULT% set /a MUL=%NUM1% * %NUM2% echo 積 : %MUL% endlocal
GOTO でラベルに戻るか、終了ワードを検知してループを抜ける方法が一般的です。
@echo off setlocal enabledelayedexpansion set /a COUNT=0 :LOOP set "LINE=" set /p LINE=入力(quit で終了): if /i "%LINE%"=="quit" goto DONE if "%LINE%"=="" goto LOOP set /a COUNT+=1 echo [!COUNT!] !LINE! goto LOOP :DONE echo 合計 %COUNT% 件の入力を受け取りました。 endlocal
コマンドライン引数(%1)がある場合はそちらを使い、ない場合だけ set /p で入力を求めるパターンは自動化と対話の両立に便利です。
@echo off
setlocal
rem 引数があればそれをそのまま使う
set "TARGET=%~1"
rem 引数がない場合だけ入力を求める
if "%TARGET%"=="" (
set /p TARGET=処理対象のファイル名を入力:
)
echo 対象: %TARGET%
endlocal
まとめ
| 目的 | 推奨方法 | ポイント |
|---|---|---|
| 文字列・パスを自由入力 | set /p | 事前に変数を空初期化。遅延展開で ! 参照が安全 |
| デフォルト値を持つ入力 | set “VAR=default” + set /p VAR= | 空入力で変数値が変わらない仕様を利用 |
| Y/N・1キー選択 | choice /c | ERRORLEVEL は大きい値から降順判定 |
| 数値範囲バリデーション | set /a + if LSS/GTR | 非数値入力は set /a で 0 に変換されてしまうため別途チェック |
| メニュー選択 | set /p + goto ラベル | choice が使えない多項目に有効 |
| タイムアウト付き確認 | choice /t /d | set /p にはタイムアウト機能なし |
対話型スクリプトは set /p で文字列・数値、choice で1キー選択と使い分けるのが基本です。入力値は必ずバリデーションしてから処理に使い、重要な操作の前には必ず Y/N 確認を入れましょう。
FOR ループと組み合わせた反復処理は bat の FOR 文の使い方完全ガイドを、ラベルと GOTO による処理の流れ制御は bat のラベル・GOTO・CALL 完全ガイドも合わせてご覧ください。
