我详细解释了什么aschipfl写在他的评论已绝对正确。
这两个批处理文件也可在Windows 2000和Windows XP上使用,也可使用cmd.exe
作为命令解释程序。批处理文件不能在MS-DOS,Windows 95和Windows 98上使用非常有限的command.com
作为命令解释程序。
可以在命令提示符窗口中使用参数/?
执行命令以获取输出对此命令的帮助。在帮助中写入并启用了命令扩展这意味着仅在基于Windows NT的Windows版本上支持cmd.exe
,并且不支持由MS-DOS或Windows 9x使用command.com
。这意味着例如for /F
或if /I
或call :Subroutine
在Windows 9x上或在基于Windows NT的Windows上显式禁用命令扩展时不可用。在Windows 9x上,甚至不可能使用"%~1"
或"%~nx1"
。
第一个批处理文件执行FOR循环只有1命令恰好1次:
set "dt=%%a"
所有其它命令后FOR循环完成以下被执行。换句话说,第一批处理文件中的循环不使用命令块在循环内运行多个命令。
只要Windows NT命令解释器检测到命令行上的命令块的开头,它此命令行上执行的命令在首次使用前处理整个命令块。
这意味着第二批文件中使用%Variable%
所有变量引用已经膨胀FOR执行该命令之前,并在命令块中的命令上述所限定FOR命令行然后用变量的值来执行。这可以通过从批处理文件的第一行去除@echo off
或它从一个命令提示窗口内更改为@echo ON
和运行批处理文件中可以看出,因为现在可以看出与(
定义的命令行分别整个命令块... )
是通过命令解释器预处理后真正执行。
所以每当一个环境变量被定义或命令块内进行修改并将其值在同一个命令块引用的,有必要使用延迟扩展或使用的解决方法。
一种解决方法如下所示:
setlocal EnableExtensions DisableDelayedExpansion
set "FolderPath=%SystemRoot%\System32"
for /F "skip=5 tokens=1,2,4 delims= " %%a in ('dir /AD /TC "%FolderPath%\."') do if "%%c"=="." (
set "VarA=%%a"
set "VarB=%%b"
call echo %%VarA%%, %%VarB%%
call set "Day=%%VarA:~0,2%%
call echo %%Day%%
)
endlocal
pause
由于没有@echo off
在这个批处理代码可在执行批处理文件,在这里发生的事情可以看到顶部。在处理命令块时,每个%%
都被修改为%
。所执行的是命令行。
call echo %VarA%, %VarB%
call set "Day=%VarA:~0,2%
call echo %Day%
CALL用于处理该行的其余部分的第二时间与不具有或具有字符串替换可以通过相应的值替换环境变量引用运行ECHO和SET命令的命令。
另一个解决方法以避免延迟扩展使用子程序:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "FolderPath=%SystemRoot%\System32"
for /F "skip=5 tokens=1,2,4 delims= " %%a in ('dir /AD /TC "%FolderPath%\."') do if "%%c"=="." call :ProcessCreationDate "%%a" "%%b"
endlocal
pause
goto :EOF
:ProcessCreationDate
echo %~1, %~2
set "Day=%~1"
set "Day=%Day:~0,2%
echo %Day%
goto :EOF
子程序是例如嵌入当前批处理文件中的另一个批处理文件。
第一goto :EOF
通过的子程序的代码避免下降。
第二goto :EOF
不会是必要的,如果上述的线是批处理文件的最后一行。但是,尽管如此,仍然建议使用它,以便在后面的更多命令行中像第二个子例程一样添加。
第二个批处理文件是获得在其上创建指定的文件夹的一天。可以在不使用延迟扩展和任何解决方法的情况下对此批处理文件进行编码。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "FolderPath=%SystemRoot%\System32"
for /F "skip=5 tokens=1,2,4 delims= " %%a in ('dir /ad /tc "%FolderPath%\." 2^>nul') do if "%%c"=="." set "CreationDate=%%a, %%b" & goto OutputDateAndDay
echo Failed to get creation date of "%FolderPath%"
endlocal
pause
goto :EOF
:OutputDateAndDay
echo %CreationDate%
set "Day=%CreationDate:~0,2%
echo %Day%
endlocal
pause
一旦与指定的文件夹的创建日期感兴趣的行被找到,创建日期/时间被分配到环境变量和FOR退出循环使用命令GOTO继续执行在下面的标签上。对于&
运营商的含义见Single line with multiple commands using Windows batch file。
这种解决方案比所有其他方法更好,因为FOR循环执行与3个命令IF单个命令行,SET和GOTO只有一个时间,这使得该解决方案是最快的。并且,当无法确定目录的创建日期时,会输出错误消息,因为该目录根本不存在。
当然也有可能还添加了GOTO命令的其他解决方案,一旦目录的创建日期被确定和输出退出FOR循环。尽管如此,最后的解决方案仍然是最快速并且以我的观点来看最适合这项任务的解决方案。
顺便说一句:所有发布的批处理文件的例子都在Windows XP上测试过,并产生了预期的输出。
延迟扩展功能在Windows XP下可用。无论如何,为了避免它,使用'call echo %% vara %%,%% varb %%'和'call set day = %% vara:〜0.2 %%'这样的调用语法,或者移动主体循环放入一个[子例程](http://ss64.com/nt/call.html)中,通过'call'调用它作为[参数]传递所有相关值(http:ss64.com/nt/ syntax-args.html)并在那里使用普通的'%' - 扩展;参考也[函数的概念](https://ss64.com/nt/syntax-functions.html)... – aschipfl