【问题标题】:Nested DOS For Loop Issues嵌套 DOS For 循环问题
【发布时间】:2011-09-18 15:32:31
【问题描述】:

我使用此批处理文件的目标是快速找出用户安装了多少防病毒应用程序。我打算通过使用两个 for 循环来做到这一点:

  • 外循环:遍历 Program Files 目录中的文件夹名称
  • 内循环:遍历常用防病毒名称列表(AVList 变量),查找当前目录名称的匹配项并将每个匹配项附加到 AntiVirus 变量。

话虽如此,这是我失败的代码。我得到的错误是 "" 此时是意外的。。请注意,我目前在 AVList 变量中的 Program Files 中有文件夹名称(用于测试目的)。

::@echo off
::variables
set AntiVirus="Initial Value"
set AVList=(adobe ccleaner auslogics)

SETLOCAL EnableDelayedExpansion

echo Checking Program Files...

if "%Processor_Architecture%" == "AMD64" (
echo 64-bit OS
echo.
for /d %%f in ("%ProgramFiles(x86)%\*") do (
   echo "%%f"
   SET "folder=%%f"
   REM Begin loop to search substrings with words in AVList
   Call:SearchAV "%folder%"
   )
) 
else echo 32-bit OS

echo.
echo AntiVirus: %AntiVirus%
echo.

for /d %%g in ("%ProgramFiles%\*") do (
   echo "%%g"
   SET "folder=%%g"
   REM Begin loop to search substrings with words in AVList
   Call:SearchAV "%folder%"
   )
)

:SearchAV
for %%v in ("%AVList%") do (
  echo "%%v"
  SET "av=%%v"
  if /I NOT "!~1:av=!"=="!~1!" set AntiVirus="%AntiVirus%%av%"
 )
GOTO:EOF

echo.
echo.
echo %AntiVirus% found
echo.
echo Script created by Matthew Ammann, revised by Andriy M from StackOverflow

@pause

这是重定向到日志文件的输出:

C:\AVFinder>set AntiVirus="Initial Value" 

C:\AVFinder>set AVList=(adobe ccleaner auslogics) 

C:\AVFinder>SETLOCAL EnableDelayedExpansion 

C:\AVFinder>echo Checking Program Files... 
Checking Program Files...

C:\AVFinder>if "AMD64" == "AMD64" (
echo 64-bit OS  
 echo. 
 for / %f in ("C:\Program Files (x86)\*") do (
echo "%f"  
 SET "folder=%f"  
 REM Begin loop to search substrings with words in AVList  
 Call:SearchAV "C:\Program Files (x86)\Adobe" 
) 
) 
64-bit OS


C:\AVFinder>(
echo "C:\Program Files (x86)\Adobe"  
 SET "folder=C:\Program Files (x86)\Adobe"  
 REM Begin loop to search substrings with words in AVList  
 Call:SearchAV "C:\Program Files (x86)\Adobe" 
) 
"C:\Program Files (x86)\Adobe"
"" was unexpected at this time.

C:\AVFinder>  if /I NOT "!~1:av=!"=="!~1!" set AntiVirus=""Initial Value""(adobe ccleaner auslogics)""

我哪里错了?

更新:我终于找到了一些时间来解决这个问题。这是更新的代码:

::This script is licensed under the Creative Commons Attribution license (CC BY 3.0) 
::Simply mention the original author in the source code if you make a derivative work.

@echo off
::variables
set AntiVirus=
set AVList=(norton mcafee kaspersky symantec avg comodo avast avira webroot eTRUST)

SETLOCAL EnableDelayedExpansion

echo Checking Program Files...

if "%Processor_Architecture%" == "AMD64" (
echo 64-bit OS
echo.
for /d %%f in ("%ProgramFiles(x86)%\*") do (
   echo "%%f"
   SET "path=%%f"
   Call:SearchAV "!path!"
   )
) else echo 32-bit OS

for /d %%g in ("%ProgramFiles%\*") do (
   echo "%%g"
   SET "path=%%g"
   Call:SearchAV "!path!"
   )
)
goto :END

:SearchAV
FOR %%a in %AVLIST% do (
  set res="%~n1"
  set res=!res:%%a=!
  if NOT "%~n1" ==!res! (
        ECHO "%~n1"  contains %%a
        if [!AntiVirus!] == [] (
            set AntiVirus="%~n1"
        ) else (
            set AntiVirus=!AntiVirus!, "%~n1"
        )   
    )
)
goto :eof

:END
echo.
echo.
echo !AntiVirus! found
echo.
echo Script created by Matthew Ammann, revised by members of Stack Overflow
echo 

@pause

【问题讨论】:

    标签: function loops batch-file dos


    【解决方案1】:

    我发现了几个问题

    1.-您拥有:searchAV 例程的位置会阻止执行最终代码。因此,将例程移至 BAT 文件的底部;并将PAUSE 替换为GOTO :EOF。见HELP CALL

    2.- 在循环中设置环境变量需要延迟扩展才能正确分配。延迟扩展需要!VAR! 符号进行检查。因此,将%FOLDER% 更改为!FOLDER!。但是,无论如何您都不需要它,因为您可能会直接使用循环变量 %%g 在您的情况下。见HELP SET

    3.- 循环字符串列表中的所有项目不适用于 FOR 命令和您使用的语法。见HELP FOR

    因此,请查看这段摘录,了解如何更正 BAT 文件...

    @ECHO off
    SETLOCAL enabledelayedexpansion
    set AVLIST=(Windows Microsoft)
    FOR /d %%a in ("%ProgramFiles%\*") do (
       CALL :searchAV "%%a"
       )
    GOTO :eof
    
    :searchAV
    FOR %%a in %AVLIST% do (
      set res=%1
      set res=!res:%%a=!
      if NOT %1==!res! ECHO %1 contains %%a
     )
    GOTO :eof
    

    【讨论】:

    • 我意识到这已经晚了大约一个月,但我想跟进。感谢您的帮助,我已经在原帖中发布了最终代码!
    【解决方案2】:

    "" was unexpected at this time. 错误来自SearchAV 子例程中set AntiVirus="%AntiVirus%%av%" 中的引号。 %av% 设置为"%AVList%",即:"(adobe ccleaner auslogics)",由于%AntiVirus% 开头为空,您尝试将AntiVirus 设置为""(adobe ccleaner auslogics)""SET 似乎不喜欢这里的空引号,因此出现了问题。

    除此之外,您可能还需要考虑以下几点:

    • else echo 32-bit OS 需要与其对应的if 在同一行。
    • 第一个和第二个 for 循环:%folder% 需要更改为 !folder! 才能从延迟的变量扩展中受益。
    • :SearchAV 子例程:for 循环不会遍历防病毒名称(%%v 保持为 "(adobe ccleaner auslogics)"!~1:av=! 始终等于 av=!~1! 保持为空)。我会改为使用 for /f 来标记列表。
    • 需要在第二个 for 循环结束后添加 goto,以免再次执行子例程。

    这是我的尝试:

    @echo off
    set AntiVirus=
    set AVList=Norton AntiVirus:ccleaner:auslogics
    
    SETLOCAL EnableDelayedExpansion
    
    echo Checking Program Files...
    
    if "%Processor_Architecture%" == "AMD64" (
    echo 64-bit OS
    echo.
      for /d %%f in ("%ProgramFiles(x86)%\*") do (
        echo %%f
        SET folder=%%f
        REM Begin loop to search substrings with words in AVList
        call :SearchAV "!folder!"
      )
    ) else echo 32-bit OS
    
    echo.
    echo AntiVirus (x86): %AntiVirus%
    echo.
    
    set AntiVirus=
    for /d %%g in ("%ProgramFiles%\*") do (
       echo %%g
       SET folder=%%g
       REM Begin loop to search substrings with words in AVList
       Call:SearchAV "!folder!"
       )
    )
    
    echo.
    echo AntiVirus: %AntiVirus%
    goto :end
    
    :SearchAV
    set list=%AVList%
    :tokenize
    for /f "tokens=1* delims=:" %%v in ("!list!") do (
      SET av=%%v
      SET list=%%w
      if /I "!av!" == "%~n1" ( 
        if [!AntiVirus!] == [] (
            set AntiVirus=!av!
        ) else (
            set AntiVirus=!AntiVirus!, !av!
        )
      )
    )
    if not [!list!] == [] goto :tokenize
    goto :eof
    
    :end
    

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多