変数と展開
代入
書き方 意味 備考
set VAR=値代入 = の前後に空白を入れない。set VAR = 値 は変数名が VAR 、値が 値 になる
set "VAR=値"代入(推奨形) 値の末尾に空白が付かない。値に & や | を含められる(ただし読み出しは !VAR! で行う。下の注意を参照)
set /a VAR=1+2数値計算して代入 /a のときだけ値が数値として扱われる。% は剰余になる(バッチ内では %%)
set /p VAR=入力: キーボード入力を代入 入力待ちになる。無人実行するバッチでは使わない
set "VAR="変数を削除 空文字の代入ではなく削除。if defined が偽になる
展開(読み出し)
書き方 展開されるタイミング 使う場面
%VAR%その行が読み込まれた時点(実行前) 通常。ただし括弧ブロックの中では値が古いままになる。展開後の行がもう一度コマンドとして読み直される
!VAR!その行が実行される直前 for や if の括弧内。setlocal enabledelayedexpansion が必要。展開結果は読み直されない ため記号を含む値でも安全
%%ffor の各回for のループ変数。バッチ内は %%、コマンドプロンプトに直接打つときは % 1つ
括弧の中では !VAR! を使う。 for や if の ( 〜 ) は、中に入る前に全体が1回だけ文字列展開されます。ループごとに変わる値を %VAR% で読むと、全周にわたって同じ値になります。
記号を含む値も !VAR! で読む。 set "MSG=Hello & World" の代入は成功しますが、echo %MSG% は展開後の echo Hello & World という行が読み直され、& がコマンド区切りとして働いて壊れます。echo !MSG! なら展開結果が読み直されないため正しく表示されます。
スコープ
書き方 意味
setlocalこれ以降の変数変更をこのスクリプト内に閉じる。書かないと呼び出し元の環境変数を書き換える
setlocal enabledelayedexpansion上に加えて !VAR! を有効にする。実質これが標準形
endlocal変更を破棄して元に戻す。スクリプト終了時に自動で行われる
endlocal & set "X=%X%"endlocal を越えて値を1つだけ持ち出す定型
引数と %~ 修飾子
引数の受け取り
書き方 意味
%0実行されたバッチ自身のパス
%1 … %91〜9番目の引数
%*すべての引数をまとめた文字列
shift引数を1つずつずらす。10個以上の引数を扱うときに使う
%~11番目の引数から前後のダブルクォートを外したもの
%~ 修飾子(%0 と %1〜、for の変数に使える)
ここでは C:\work\data\input.txt が渡された場合の展開結果を示します。
書き方 意味 展開結果
%~1クォートを外す C:\work\data\input.txt
%~f1フルパスにする C:\work\data\input.txt
%~d1ドライブ C:
%~p1パス部分 \work\data\
%~dp1ドライブ+パス C:\work\data\
%~n1拡張子なしのファイル名 input
%~x1拡張子 .txt
%~nx1ファイル名+拡張子 input.txt
%~s18.3形式の短いパス 空白を含むパスの回避に使う
%~a1ファイル属性 --a------
%~t1更新日時 2026/08/25 10:30
%~z1ファイルサイズ 1024
自分の場所を指す定型
書き方 意味 注意
%~dp0このバッチがあるフォルダ(末尾に \ 付き) "%~dp0file.txt" と連結する。"%~dp0\file.txt" は \ が二重になる
%~nx0このバッチのファイル名 使い方(usage)表示に使う
pushd "%~dp0"このバッチの場所へ移動 UNC パスでも動く。戻すときは popd
エスケープ
文字 そのまま書くと エスケープ 備考
%変数展開として解釈される %%バッチファイル内のみ。プロンプトに直接打つときは % 1つ
^次の1文字のエスケープ記号 ^^行末に置くと行継続になる
&コマンドの区切り ^&" で囲んだ中なら不要
|パイプ ^|同上
> <リダイレクト ^> ^<同上
( )ブロックの区切り ^( ^)ブロック内では特に必要になる
!遅延展開が有効なとき変数として解釈される ^^!^ が2つ 必要。^! では展開されてしまう。遅延展開が無効ならエスケープ不要
"文字列の区切り — エスケープできない。数を偶数に保つのが基本
迷ったら文字列全体を " で囲む。 & | > < ( ) はダブルクォートの内側では特別扱いされません。^ を1文字ずつ付けるより事故が少なくなります。ただし % と ! はクォートの中でも展開されるため、これだけは %% / ^^! が必要です。
! だけ ^ が2つ必要な理由
1行は「% の展開 → ^ の処理 → ! の展開」という順に解釈されます。! の展開が ^ の処理より後 にあるため、^! と書くと ^ が先に消費されて ! だけが残り、そのあと変数として展開されてしまいます。
@echo off
setlocal enabledelayedexpansion
set "MSG=VALUE"
echo 1: ^!MSG^!
echo 2: ^^!MSG^^!
1: VALUE
2: !MSG!
^^ が ^ 1つに減り、その ^ が ! の展開を止めます。! をリテラルで出したいだけなら、その箇所を setlocal disabledelayedexpansion で囲んで遅延展開を切るほうが読みやすくなります。
行継続
rem 長いコマンドを複数行に分ける(行末に ^ 、次の行は続きとして扱われる)
robocopy "C:\src" "C:\dst" ^
/E /R:1 /W:1 ^
/LOG:"%~dp0robocopy.log"
要注意 ^ の後ろに空白があると行継続として機能しません。行末は ^ で終わらせます。
条件分岐 if
基本形
書き方 意味
if "%A%"=="x" ( … )文字列の一致。両辺を " で囲むのが定型(空のときに構文エラーになるのを防ぐ)
if /i "%A%"=="x" ( … )大文字小文字を区別しない比較
if not "%A%"=="x" ( … )否定
if defined A ( … )変数が定義されているか。% で囲まない
if exist "path" ( … )ファイル・フォルダの存在。フォルダを確かめたいときは "path\" と末尾に \ を付ける
if errorlevel 1 ( … )直前の終了コードが 1以上 なら真(「1と等しい」ではない)
if %N% GEQ 10 ( … )数値比較
数値比較の演算子
演算子 意味 他言語
EQU等しい ==
NEQ等しくない !=
LSSより小さい <
LEQ以下 <=
GTRより大きい >
GEQ以上 >=
else の書き方
rem 正しい: ) と else と ( を同じ行に置く
if "%A%"=="x" (
echo A は x
) else (
echo A は x ではない
)
構文エラー ) と else を別の行に分けると動きません。if は1つの論理行として解析されるためです。
if の中で %errorlevel% は使えない。 ブロック内の %errorlevel% はブロックに入る前の値に固定されています。ブロック内で更新後の値を見るには !errorlevel! か if errorlevel 1 を使います。
繰り返し for
4つの形
形 回すもの 例
無印 ファイル名・空白区切りの文字列 for %%f in (*.txt) do echo %%f
/l数値の範囲(開始,増分,終了) for /l %%i in (1,1,5) do echo %%i
/fファイルの各行・文字列・コマンド出力 for /f "delims=" %%l in (a.txt) do echo %%l
/rサブフォルダを含むファイル for /r "C:\work" %%f in (*.log) do echo %%f
/dフォルダのみ for /d %%d in (*) do echo %%d
/f のオプション
オプション 意味
delims=,区切り文字を指定(既定は空白とタブ)。delims= と空にすると行全体を1つとして扱う
tokens=1,3取り出す列の番号。tokens=1,* で「1列目」と「残り全部」
skip=1先頭のn行を飛ばす(ヘッダ行の読み飛ばし)
eol=;この文字で始まる行を無視する(既定は ;)
usebackq引用符の意味を変える。空白を含むファイル名を読むときに必要
対象の指定と引用符
書き方 回す対象
in (a.txt)ファイル a.txt の各行
in ("文字列")その文字列そのもの(ファイルではない)
in ('コマンド')コマンドの実行結果の各行
in ("C:\a b\c.txt") + usebackq空白を含むパスのファイルの各行
rem 空白を含むパスのファイルを1行ずつ読む
for /f "usebackq delims=" %%l in ("%~dp0data file.txt") do (
echo 行: %%l
)
rem コマンドの出力を読む(usebackq のときはバッククォート)
for /f "usebackq tokens=1,2 delims=," %%a in (`type list.csv`) do (
echo 1列目=%%a 2列目=%%b
)
tokens を複数指定すると変数は自動で増える。tokens=1,2,3 で %%a を指定した場合、2列目は %%b、3列目は %%c になります。宣言は不要で、アルファベット順に割り当てられます。
ループの脱出
break はありません。goto でループの外のラベルへ飛ぶか、フラグ変数で以降の処理をスキップします。
for %%f in (*.txt) do (
if "%%~nf"=="target" goto :found
)
echo 見つかりませんでした
goto :eof
:found
echo 見つかりました
文字列操作
いずれも %VAR% 形式の変数にしか使えません。引数 %1 や for の %%f に直接は使えないため、いったん set "V=%~1" で変数に入れます。
書き方 意味 例(V=abcdefg)
%V:~0,3%0文字目から3文字 abc
%V:~3%3文字目から末尾まで defg
%V:~-2%末尾から2文字 fg
%V:~0,-2%末尾2文字を除いた残り abcde
%V:abc=X%置換 Xdefg
%V:abc=%削除(空文字に置換) defg
よく使う組み合わせ
やりたいこと 書き方
文字列を含むか判定 if not "%V:abc=%"=="%V%" ( 含む )
末尾の \ を取り除く if "%V:~-1%"=="\" set "V=%V:~0,-1%"
パスの区切りを置換 set "V=%V:\=/%"
大文字小文字を無視して置換 不可。for /f と外部コマンドを使う
置換・部分取得は !V! 形式でも書ける。 ループ内で使う場合は !V:~0,3! のように ! で囲みます。ただし値そのものに = や : が含まれると解釈が崩れるため、この記法で扱うのはパスや識別子程度にとどめるのが安全です。
リダイレクトと終了コード
リダイレクト
書き方 意味
> file標準出力をファイルへ(上書き)
>> file標準出力をファイルへ(追記)
2> file標準エラーをファイルへ
> file 2>&1標準出力と標準エラーをまとめてファイルへ
> nul出力を破棄する
2> nulエラー出力だけ破棄する
< fileファイルを標準入力として渡す
cmd1 | cmd2cmd1 の出力を cmd2 の入力へ
要注意 2>&1 は「その時点の標準出力と同じ先」を意味するため、順序が変わると結果が変わります。> file 2>&1 は両方がファイルへ、2>&1 > file は標準出力だけがファイルへ行き、エラーは画面に残ります。
終了コード
書き方 意味
%errorlevel%直前のコマンドの終了コード。0 が成功
if errorlevel 11以上(=失敗)なら真
cmd && 次cmd が成功したときだけ次を実行
cmd || 次cmd が失敗したときだけ次を実行
exit /b nこのバッチを終了コード n で終える
exit ncmd.exe そのものを終える(呼び出し元も閉じる)
goto :eofサブルーチンから戻る / スクリプトの末尾へ飛ぶ
rem 失敗したら中断する定型
copy "%SRC%" "%DST%" || (
echo コピーに失敗しました
exit /b 1
)
サブルーチン
call :log "処理を開始します"
call :log "処理が完了しました"
goto :eof
:log
echo [%DATE% %TIME%] %~1
goto :eof
call を付けずに :log へ goto すると、そこから戻ってきません。
よく使うコマンド
ファイル・フォルダ
コマンド 用途 覚えておくオプション
copyファイルのコピー /y 上書き確認なし
xcopyフォルダごとコピー /e /i /y
robocopy大量・差分コピー /e /r:1 /w:1。終了コードが 0 以外でも成功のことがある
move移動・リネーム /y
delファイル削除 /q 確認なし /s サブフォルダも
rdフォルダ削除 /s /q
mdフォルダ作成 途中の階層も自動で作られる
dir一覧 /b 名前だけ /s 再帰 /a-d ファイルのみ
テキスト・情報取得
コマンド 用途 備考
typeファイルの内容を表示 複数ファイルの連結にも使える
find文字列の検索 " で囲む必要がある。/c で件数、/v で否定
findstr正規表現の検索 /i 大小無視 /r 正規表現 /c:"..." 語句指定
where実行ファイルの場所を探す 存在確認にも使える(見つからないと終了コードが 1)
tasklistプロセス一覧 /fi "imagename eq x.exe"
chcpコードページの確認・変更 日本語環境は 932。65001(UTF-8)への変更は副作用があるため安易に使わない
制御・その他
コマンド 用途 備考
@echo off実行するコマンド自体の表示を止める 1行目に書く。先頭の @ はこの行自身を隠すため
remコメント 括弧の中でも安全。:: はラベルなので括弧内では使えない
pauseキー入力を待つ ダブルクリック実行で結果を読ませたいときに末尾へ
timeout /t 55秒待つ /nobreak でキー入力による中断を防ぐ
start ""別プロセスとして起動 第1引数はウィンドウタイトル扱いなので "" を置く
call other.cmd別のバッチを呼んで戻る call なしでは戻ってこない
pushd / popd移動して戻る UNC パスにも対応する
titleウィンドウタイトルを設定 長時間動くバッチで進捗を示すのに使える
コマンドのヘルプは コマンド /? で読める。 for /? や set /? は、この早見表より詳しい説明を出します。出力が長いので for /? | more やファイルへのリダイレクトと併せて使ってください。