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 correspondingif
.- first and second
for
loops:%folder%
needs to be changed to!folder!
to benefit from delayed variable expansion. :SearchAV
subroutine: thefor
loop does not loop over anti-virus names (%%v
stays to"(adobe ccleaner auslogics)"
,!~1:av=!
is always equal toav=
and!~1!
stays empty). I would instead use afor /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.
精彩评论