【问题标题】:Expanding env variables in runtime in windows shell在 Windows shell 中的运行时扩展环境变量
【发布时间】:2013-02-27 12:01:44
【问题描述】:

我在使用以下示例时遇到了问题。我有一个包含文件名列表的文件。我想检查这些文件是否存在,例如:

%ProgramFiles%\Internet Explorer\iexplore.exe
%SystemRoot%\sdfsdfsd.exe
%SystemRoot%\explorer.exe

每个路径都包含环境变量。

我的bat文件示例:

echo off  
for /f "tokens=*" %%a in (filelist.txt) do (  
  if exist "%%~a" (  
    echo %%~a exists  
  ) else (  
    echo %%~a doesn't exists  
  )  
)

文件名已正确加载,但我 cmd 找不到所有文件。我认为 cmd 处理器不会在路径中扩展环境变量......我该怎么做?或者可能还有其他问题。

或者我如何在变量中将! 替换为%

【问题讨论】:

    标签: cmd environment-variables windows-shell


    【解决方案1】:

    rojo 已经有了正确的想法,但没有必要求助于子程序。 call 与 e.g. 结合使用时也会导致嵌套变量的扩展。 set 命令。

    @echo off
    
    setlocal EnableDelayedExpansion
    
    for /f "tokens=*" %%a in (filelist.txt) do (
      call set fname=%%~a
      if exist "!fname!" (
        echo %%~a exists.
      ) else (
        echo %%~a doesn't exist.
      )
    )
    
    endlocal
    

    编辑: 正如@dbenham 所指出的,上述代码中的延迟扩展将导致感叹号从文件名中消失。这可以通过在循环内移动 setlocal EnableDelayedExpansion 指令并在 call set 前面加上 setlocal DisableDelayedExpansion 以防止 %fname% 泄漏到循环外来缓解。

    @echo off
    
    for /f "tokens=*" %%a in (filelist.txt) do (
      setlocal DisableDelayedExpansion
      call set fname=%%~a
      setlocal EnableDelayedExpansion
      if exist "!fname!" (
        echo %%~a exists.
      ) else (
        echo %%~a doesn't exist.
      )
      endlocal
    )
    

    【讨论】:

    • 是的,但我的 ocd 在 call set varname 处发出刺痛感,因为在脚本退出后,%fname% 仍被定义为孤立的环境变量。在我看来,call SET 破坏了setlocal
    • 另外,延迟扩展会损坏任何包含! 的文件名(我知道这种情况很少见,但确实会发生)。该问题可以通过在循环中打开和关闭延迟扩展来解决。
    • @rojo call setsetlocal 中使用时不会定义 %fname%
    • 而不是最后的set fname=,您可以简单地在定义fname之前添加一个setlocal disableDelayedExpansion,然后在最后添加一个endlocal。这样,在循环进入时是否启用或禁用延迟扩展都无关紧要。现在,如果循环的目的是设置一些环境变量,那么它会变得有点复杂,因为它们必须在 endlocal(s) 之后设置。
    • @Ansgar-Wiechers,谢谢!我得到了你的第二个例子,只做了一个小的修改:使用endlocal & endlocal 而不是endlocal。因为Maximum setlocal recursion level reached. 错误。神奇之处在于call set fname=%%~a 行。
    【解决方案2】:

    尝试使用call 来强制评估文本文件中的变量。

    @echo off
    setlocal
    for /f "tokens=*" %%a in (filelist.txt) do (
        call :checkExists "%%~a"
    )
    goto :EOF
    
    :checkExists <filename>
    if exist %1 (
        echo %~1 exists
    ) else (
        echo %~1 doesn't exists
    )
    goto :EOF
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-03
      • 2020-09-05
      • 2020-03-04
      • 2018-07-23
      • 1970-01-01
      相关资源
      最近更新 更多