嵌套DOS For循环问题

时间:2011-09-18 15:32:31

标签: function loops batch-file dos

我对此批处理文件的目标是快速了解用户安装了多少个防病毒应用程序。我计划通过使用两个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

2 个答案:

答案 0 :(得分:5)

我看到了几个问题

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

答案 1 :(得分:2)

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

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

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

以下是我的尝试:

!~1!

希望这有帮助。