开发者

Nested DOS For Loop Issues

开发者 https://www.devze.com 2023-04-05 12:02 出处:网络
My goal with this batch file is to quickly find out how many antivirus applications a user has installed. I plan to do this by using two for loops:

My goal with this batch file is to quickly find out how many antivirus applications a user has installed. I plan to do this by using two for loops:

  • Outer loop: Iterate through the folder names in the Program Files directory
  • Inner loop: Iterate through a list of common antivirus names (the AVList variable), looking for matches to the current directory name and appending each match to the AntiVirus variable.

With that said, here's my failing code. The error I'm getting is "" was unexpected at this time.. Note that I currently have names of folders in my Program Files in the AVList variable (for testing purposes).

::@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

Here's the output redirected to a logfile:

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)""

Where am I going wrong?

UPDATE: I finally found some time to fix this. Here's the updated code:

::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


I see several problems

1.-The place you have the :searchAV routine prevents the final code from executing. So, move the routine to the bottom of the BAT file; and replace the PAUSE by an GOTO :EOF. See HELP CALL

2.- Setting an environment variable in a loop needs delayed expansion for proper assignment. And delayed expansion needs the !VAR! notation for inspection. So, change %FOLDER% to !FOLDER!. But, you don't need it anyway, as you might directly use the loop variable, %%g in your case. See HELP SET.

3.- Looping on all the items in a string list does not work with the FOR command with the syntax you used. See HELP FOR.

So, take a look at this excerpt for ideas on how to correct your BAT file...

@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


The "" was unexpected at this time. error comes from the surrounding quotes in set AntiVirus="%AntiVirus%%av%" in your SearchAV subroutine. %av% is set to "%AVList%", that is: "(adobe ccleaner auslogics)", and because %AntiVirus% is empty at the beginning, you are trying to set AntiVirus to ""(adobe ccleaner auslogics)"". SET does not seem to like the empty quotes here, hence the problem.

Besides this, you may also want to consider the following points:

  • else echo 32-bit OS needs to be on the same line as its corresponding if.
  • first and second for loops: %folder% needs to be changed to !folder! to benefit from delayed variable expansion.
  • :SearchAV subroutine: the for loop does not loop over anti-virus names (%%v stays to "(adobe ccleaner auslogics)", !~1:av=! is always equal to av= and !~1! stays empty). I would instead use a for /f to tokenize the list.
  • a goto needs to be added after the end of the second for loop so that you do not go through the subroutine again.

Here is my attempt at it:

@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

Hope this helps.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号