batファイル内のfor文で回数ごとに変数を取得しようとすると、「変数なのに変わんないじゃん」といったことが起こります。
普段の文法で書いたtest1.bat(即時展開環境変数)
timeの結果がすべて一緒です。
これはどういうことかというと、ステートメント(ここではfor do ( ~ )まで)がすべて読み込んだあとに変数を決定するらしく、for文内では、一緒の値になってしまうのです。
C:\tmp>type test1.bat
@echo off
for /l %%a in (1,1,5) do (
timeout /t 1
echo %%a %time% >> test1.log
)
C:\tmp>
C:\tmp>type test1.log
1 19:06:40.68
2 19:06:40.68
3 19:06:40.68
4 19:06:40.68
5 19:06:40.68
C:\tmp>;
@echo off
for /l %%a in (1,1,5) do (
timeout /t 1
echo %%a %time% >> test1.log
)
C:\tmp>
C:\tmp>type test1.log
1 19:06:40.68
2 19:06:40.68
3 19:06:40.68
4 19:06:40.68
5 19:06:40.68
C:\tmp>;
一方、遅延環境変数を使って書いたtest2.bat
timeの結果がきちんと1秒ごとに表示されていることがわかります。
C:\tmp>type test2.bat
@echo off
setlocal enabledelayedexpansion
for /l %%a in (1,1,5) do (
timeout /t 1
echo %%a !time! >> test2.log
)
endlocal
C:\tmp>
C:\tmp>type test2.log
1 19:06:48.15
2 19:06:49.12
3 19:06:50.19
4 19:06:51.16
5 19:06:52.13C:\tmp>
C:\tmp>
@echo off
setlocal enabledelayedexpansion
for /l %%a in (1,1,5) do (
timeout /t 1
echo %%a !time! >> test2.log
)
endlocal
C:\tmp>
C:\tmp>type test2.log
1 19:06:48.15
2 19:06:49.12
3 19:06:50.19
4 19:06:51.16
5 19:06:52.13C:\tmp>
C:\tmp>
遅延環境変数の使い方
以下を対象ステートメントの前に書き、変数の%の代わりに!を使います。
「ここからは遅延環境変数が有効だよ」という意味。
※endlocalはつけなくても大丈夫
setlocal enabledelayedexpansion