修改for循环在批处理脚本中不使用delayedexpansion

用户6003691

我努力理解for..do循环语法及其%%变量的使用我已经经历了2个具体的例子/实施了其中一个for循环不使用DELAYEDEXPANSION,另一个在那里它使用DELAYEDEXPANSION!符号。第一个 for 循环似乎与 Windows XP 等旧操作系统兼容,而第二个 for 循环示例不兼容。

具体来说,第一个 for 循环示例取自此答案(与相关),第二个 for 循环示例取自此答案

下面复制了两个示例的修改代码:

第一个 for 循环

for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YY=%dt:~2,2%"
set "YYYY=%dt:~0,4%"
set "MM=%dt:~4,2%"
set "DD=%dt:~6,2%"
set "HH=%dt:~8,2%"
set "Min=%dt:~10,2%"
set "Sec=%dt:~12,2%"
set "datestamp=%YYYY%%MM%%DD%"
set "timestamp=%HH%%Min%%Sec%"
echo datestamp: "%datestamp%"
echo timestamp: "%timestamp%"

第二个 for 循环

SETLOCAL ENABLEDELAYEDEXPANSION
set "path_of_folder=C:\folderA\folderB"

for /f "skip=5 tokens=1,2,4 delims= " %%a in (
 'dir /ad /tc "%path_of_folder%\."') do IF "%%c"=="." (
  set "dt=%%a"
  set vara=%%a
  set varb=%%b
  echo !vara!, !varb!
  set day=!vara:~0,2!
  echo !day!
)

由于我一直在阅读并看到延迟扩展(或!符号)与旧操作系统(例如 Windows XP)不兼容的问题,我想看看如何像第一个循环一样编写第二个循环;即不使用DELAYEDEXPANSION.

莫菲

我详细解释了aschipfl在他的评论中写的已经完全正确的内容。

这两个批处理文件也可在 Windows 2000 和 Windows XP 上使用,也cmd.exe可用作命令解释器。批处理文件在 MS-DOS、Windows 95 和 Windows 98 上无法使用非常有限command.com的命令解释器。

可以/?在命令提示符窗口中使用参数执行命令,以获取此命令的帮助输出。使用启用的命令扩展编写帮助时,这意味着仅受cmd.exe基于 Windows NT 的 Windows 版本支持,而不受 MS-DOS 或 Windows 9x 支持,使用command.com. 这意味着,例如for /Fif /Icall :Subroutine在 Windows 9x 上或在基于 Windows NT 且明确禁用命令扩展的 Windows 上可用。在 Windows 9x 上,甚至无法使用"%~1""%~nx1".

第一个批处理文件在FOR循环中只执行1 个命令,恰好 1 次:

set "dt=%%a"

FOR循环完成后执行下面的所有其他命令换句话说,第一个批处理文件中FOR循环不使用命令块在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用于再次处理行的其余部分以运行ECHOSET命令,其中环境变量引用被替换为它们的相应值,没有或有字符串替换。

避免延迟扩展的另一种解决方法是使用子例程:

@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

一旦找到具有指定文件夹创建日期的感兴趣的行,创建日期/时间将分配给环境变量,并使用命令GOTO退出FOR循环以继续在下面的标签上执行。运算符的含义参见使用 Windows 批处理文件的单行多命令&

此解决方案优于所有其他方法,因为FOR循环仅执行 3 个命令IFSETGOTO一次的单个命令行,这使得该解决方案最快。当由于目录根本不存在而无法确定目录的创建日期时,它会输出错误消息。

当然,一旦确定并输出目录的创建日期,也可以在其他解决方案上添加GOTO命令以退出FOR循环。然而,最后一个解决方案是最快的,在我看来,最适合这项任务的解决方案。

顺便说一句:所有发布的批处理文件示例都在 Windows XP 上进行了测试并产生了预期的输出。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

批处理脚本中的循环通配符匹配

来自分类Dev

批处理脚本循环

来自分类Dev

如何使用批处理脚本仅获取修改年份?

来自分类Dev

如何使用 % 或 ! 在批处理脚本中

来自分类Dev

批处理脚本“继续”循环?

来自分类Dev

在循环批处理脚本(Windows,批处理脚本)的路径中使用findstr命令变量扩展

来自分类Dev

在批处理中的FOR循环末尾使用if条件

来自分类Dev

在循环中使用%time和%date时,批处理脚本中的时间戳相同

来自分类Dev

使用批处理脚本在多个命令提示符中运行无限循环

来自分类Dev

如何在批处理脚本中增加循环变量?

来自分类Dev

FOR循环变量中的空格问题-批处理脚本

来自分类Dev

我的批处理脚本中的循环有什么问题?

来自分类Dev

嵌套for循环,设置变量以及是否在批处理脚本中

来自分类Dev

在批处理脚本中 for 循环后不打印任何内容

来自分类Dev

如何在批处理脚本中包含或循环

来自分类Dev

使用批处理脚本循环写入文件的特定行

来自分类Dev

如何使用批处理文件循环imacro脚本

来自分类Dev

使用批处理脚本循环写入文件的特定行

来自分类Dev

如何使用延迟扩展处理批处理脚本中的值

来自分类Dev

批处理脚本中的if语句

来自分类Dev

批处理脚本在for循环后结束

来自分类Dev

使用WMIC批处理循环

来自分类Dev

使用批处理脚本提取文件中的路径列表

来自分类Dev

使用Windows批处理脚本在CSV文件中添加列

来自分类Dev

使用脚本在批处理文件中运行django shell

来自分类Dev

如何使用批处理脚本遍历目录中的文件

来自分类Dev

使用批处理脚本在目录中获取文件名

来自分类Dev

使用批处理脚本在文件中插入行

来自分类Dev

Windows批处理脚本,并使用“!”处理文件名 For循环中的感叹号

Related 相关文章

  1. 1

    批处理脚本中的循环通配符匹配

  2. 2

    批处理脚本循环

  3. 3

    如何使用批处理脚本仅获取修改年份?

  4. 4

    如何使用 % 或 ! 在批处理脚本中

  5. 5

    批处理脚本“继续”循环?

  6. 6

    在循环批处理脚本(Windows,批处理脚本)的路径中使用findstr命令变量扩展

  7. 7

    在批处理中的FOR循环末尾使用if条件

  8. 8

    在循环中使用%time和%date时,批处理脚本中的时间戳相同

  9. 9

    使用批处理脚本在多个命令提示符中运行无限循环

  10. 10

    如何在批处理脚本中增加循环变量?

  11. 11

    FOR循环变量中的空格问题-批处理脚本

  12. 12

    我的批处理脚本中的循环有什么问题?

  13. 13

    嵌套for循环,设置变量以及是否在批处理脚本中

  14. 14

    在批处理脚本中 for 循环后不打印任何内容

  15. 15

    如何在批处理脚本中包含或循环

  16. 16

    使用批处理脚本循环写入文件的特定行

  17. 17

    如何使用批处理文件循环imacro脚本

  18. 18

    使用批处理脚本循环写入文件的特定行

  19. 19

    如何使用延迟扩展处理批处理脚本中的值

  20. 20

    批处理脚本中的if语句

  21. 21

    批处理脚本在for循环后结束

  22. 22

    使用WMIC批处理循环

  23. 23

    使用批处理脚本提取文件中的路径列表

  24. 24

    使用Windows批处理脚本在CSV文件中添加列

  25. 25

    使用脚本在批处理文件中运行django shell

  26. 26

    如何使用批处理脚本遍历目录中的文件

  27. 27

    使用批处理脚本在目录中获取文件名

  28. 28

    使用批处理脚本在文件中插入行

  29. 29

    Windows批处理脚本,并使用“!”处理文件名 For循环中的感叹号

热门标签

归档