Delayed Expansion
You update a variable inside a FOR loop or IF block in a batch file, but echo still prints the old value. This is one of the most common problems in batch scripting.
The fix is delayed environment variable expansion.
In short: add setlocal enabledelayedexpansion and replace %variable% with !variable! inside the block. This article explains the expansion timing behind the problem and shows how to use delayed expansion with sample code.
The Problem: Variables Do Not Update Inside Blocks
Look at the following batch file.
@echo off
setlocal
set COUNT=0
for %%f in (*.txt) do (
set /a COUNT+=1
echo File %COUNT%: %%f
)
echo Total: %COUNT%
endlocal
This script tries to count text files, but the result is not what you expect.
COUNT is always displayed as 0.
The Cause: When Variables Are Expanded
In batch files, a block enclosed in parentheses () is parsed as a whole before it runs. During parsing, %variable% is replaced with the value it had before the block started.
In the example above, %COUNT% is replaced with 0 (its value before the for loop), so updating it inside the loop has no visible effect.
rem When the whole block is parsed, %COUNT% is replaced with 0
for %%f in (*.txt) do (
set /a COUNT+=1
echo File 0: %%f <- %COUNT% has already become 0
)
The Solution: Enable Delayed Expansion
Enable delayed expansion and use !variable! instead of %variable%. The variable is then expanded at execution time.
Steps
- Write
setlocal enabledelayedexpansion - Change variable references inside the block to
!variable!
@echo off
setlocal enabledelayedexpansion
set COUNT=0
for %%f in (*.txt) do (
set /a COUNT+=1
echo File !COUNT!: %%f
)
echo Total: !COUNT!
endlocal

中小企業経営者のためのRPA入門 RPA導入を成功させる方法

60分でわかる! AIエージェント 超 入門

コマンドラインの黒い画面が怖いんです。

知識・才能ゼロでもらく~に月10万円稼ぐ! よくわかるAI副業超入門
Now COUNT is incremented correctly.
%variable% vs. !variable!
| Syntax | Expanded | Use for |
|---|---|---|
%variable% | At parse time | Ordinary references outside blocks |
!variable! | At execution time | Variables that change inside a block |
setlocal enabledelayedexpansion stays in effect until the matching endlocal (or until the batch file ends if there is none). Variables changed inside setlocal are also restored by endlocal. To enable it for the whole script, put it at the top of the file.
The Same Problem in IF Blocks
The same problem occurs in IF blocks, not just FOR loops.
@echo off
setlocal
set RESULT=NG
if exist "data.txt" (
set RESULT=OK
echo Result: %RESULT%
)
Even when data.txt exists, this prints Result: NG. Fix it with delayed expansion.
@echo off
setlocal enabledelayedexpansion
set RESULT=NG
if exist "data.txt" (
set RESULT=OK
echo Result: !RESULT!
)
Typical Cases That Need Delayed Expansion
Numbering file names
@echo off
setlocal enabledelayedexpansion
set NUM=0
for /f "delims=" %%f in ('dir /b /a-d *.jpg') do (
set /a NUM+=1
set PADDED=00!NUM!
set PADDED=!PADDED:~-3!
ren "%%f" "photo_!PADDED!.jpg"
)
echo Renaming finished.
endlocal
If you rename files inside for %%f in (*.jpg), renamed files may be picked up by the loop again. Reading the output of dir /b with for /f loops over the list as it was before the loop started, which is safer.
Accumulating values in a variable
@echo off
setlocal enabledelayedexpansion
set ALL_FILES=
for %%f in (*.txt) do (
set ALL_FILES=!ALL_FILES! %%f
)
echo Files found:!ALL_FILES!
endlocal
Things to Watch Out For
Strings that contain an exclamation mark !
When delayed expansion is enabled, ! in a string is treated as a variable delimiter. Be careful with file names and paths that contain !.
rem With delayed expansion on, the "!" is lost and this prints C:\ImportantFiles
set PATH_WITH_BANG=C:\Important!Files
echo !PATH_WITH_BANG!
With delayed expansion enabled, strings containing ! may be expanded unexpectedly. If you need to handle such paths, disable delayed expansion for that part with setlocal disabledelayedexpansion, or escape the character as ^^!.
Use it only where needed
Delayed expansion is powerful, but you do not need it everywhere. Use ordinary %variable% for simple references outside blocks.
Summary
| Item | Details |
|---|---|
| How to enable | setlocal enabledelayedexpansion |
| Delayed reference syntax | !variable_name! |
| Where the problem occurs | Inside FOR loops and IF blocks |
| Caution | Strings containing ! can be misinterpreted |
Delayed expansion is essential knowledge for handling variables correctly inside loops and blocks in batch files.