Windowsのバッチファイル(.bat/.cmd)で FOR
や IF
を使った処理を記述していると、
「変数が更新されない」「値がループ中で変わらない」といった問題に直面することはありませんか?
その原因は、変数が「実行前に展開される」ためです。
この問題を解消するための鍵となるのが、**setlocal EnableDelayedExpansion
(遅延環境変数展開)**です。
この記事では、初心者でも理解できるように「なぜ必要なのか」「どう使うのか」を実例付きで丁寧に解説します。
✅ 通常の変数展開とその問題点
バッチファイルでは、変数は通常 %変数名%
の形式で展開されます。
しかし %変数名%
はFORループ開始前に固定されるため、ループ内で更新しても反映されません。
❌ 例:変数が更新されていないケース(失敗例)
🔍 この場合、出力は以下の通りになります。
→ ループの中でカウントを増やしているのに、%cnt%
は常に最初の「0」のままです。
✅ 解決策:EnableDelayedExpansionを使って遅延展開する
変数を**実行時に展開する方式(遅延展開)**に切り替えることで、この問題を解消できます。
そのために必要なのが、以下の1行です:
さらに、変数の表記を %変数名%
から !変数名!
に変更します。
✅ 正しい例:遅延展開を使った成功例
📌 出力結果:
✅ !cnt!
を使うことで、ループごとに最新の値が展開されるようになります。
✅ なぜ「!」に変える必要があるのか?
展開方法 | 展開タイミング | 書き方 | 主な用途 |
---|---|---|---|
通常展開 | コマンド実行前 | %変数名% | 単純な処理 |
遅延展開 | 実行中(リアルタイム) | !変数名! | FOR/IF などのループ内 |
✅ 応用例:文字列置換との組み合わせ
以下のような「文字列の一部を動的に置換する」ケースでも遅延展開が役立ちます。
✅ EnableDelayedExpansionが2回登場することがある理由
バッチファイル内で call
されたサブルーチンやネスト構造がある場合、setlocal/endlocal のスコープが階層ごとに分かれるため、そのたびに再設定するケースがあります。
✅ まとめ
項目 | 内容 |
---|---|
何のための機能? | 変数をリアルタイムで展開するため |
必要な記述 | setlocal EnableDelayedExpansion |
書き換える箇所 | %変数名% → !変数名! |
主な利用シーン | FOR/IFループ内で変数が更新される処理 |
書き忘れると… | 値が変わらず意図しない結果になる |
✅ 次のステップ:あなたのバッチにも適用してみよう!
もし今お使いのバッチで「ループ中に値が変わらない」「文字列置換が動かない」といった問題がある場合、ぜひ EnableDelayedExpansion
を追加してみてください。