【bat】バッチファイルでユーザー入力を受け取る方法完全ガイド|set /p・バリデーション・Y/N確認・メニュー・デフォルト値まで

バッチファイル(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 は入力内容を無検証で変数に入れる
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
errorlevel の判定は大きい値から行う
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)

Q 入力をパスワードのように非表示にしたい
A

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
Q タイムアウト付きの入力を実装したい
A

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 実行します
Q 入力を数値に変換して計算したい
A

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
Q ループして複数回入力を受け取りたい
A

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
Q 引数がないときだけ入力を求めたい
A

コマンドライン引数(%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 完全ガイドも合わせてご覧ください。