开发者

Batch File to Search for a String within Directory Names

My batch file terminates prematurely after I assign the first environmental variable (script output below). I've tried turning echo on, using errorlevels, sending the output to a text file, and checking syntax. I've spent several hours researching debugging batch scripts, but I have finally hit a brick wall.

Script's Goal: Search each directory name of the user's Program Files, looking for common antivirus programs. I realize that it would be easiest iterate through an array of antivirus names for this purpose, but I want to keep it simple for now.

@echo off
::variables
set AntiVirus1="Initial Value"

IF NOT ERRORLEVEL 0 echo %ERRORLEVEL%
else echo "env. variable created successfully."

for /d %%f in (""%ProgramFiles%\*"") do (
{
    IF NOT ERRORLEVEL 0 echo %ERRORLEVEL%

   echo "%%f"
   if exist /i "*McAfee*" < %%f %AntiVirus1%="McAfee"
   ::find "Norton" < %%f
   ::find 开发者_如何转开发"Comodo" < %%f
   ::find "AVG" < %%f

}

echo %AntiVirus1%

@pause

Output of this script:

C:\Users\Matt\Desktop>set AntiVirus1="Initial Value" C:\Users\Matt\Desktop>

Can someone point me to what I'm doing wrong?


UPDATE Corrected script, now working but returning incorrect results:

::@echo off
::variables
set AntiVirus1="Initial Value"

IF NOT ERRORLEVEL 0 (echo %ERRORLEVEL%) ELSE echo "env. variable created successfully."

echo Checking Program Files...
for /d %%f in ("%ProgramFiles%\*") do (
   echo "%%f"
   if %%f=="*adobe*" set AntiVirus1="adobe"
)

echo %AntiVirus1% found

@pause


First of all, ELSE must be on the same line with IF or on the same line with the closing parenthesis that pertains to IF. In you particular case you should change your first IF...ELSE command like this:

IF NOT ERRORLEVEL 0 (ECHO %ERRORLEVEL%) ELSE ECHO "env. variable created successfully."

or like this:

IF NOT ERRORLEVEL 0 (
  ECHO %ERRORLEVEL%
) ELSE ECHO "env. variable created successfully."

(Capitalisation and indentation are perfectly optional.)

Other issues:

  • Duplicated quotation marks in the FOR loop header:

    for /d %%f in (""%ProgramFiles%\*"") do (
    

    should be

    for /d %%f in ("%ProgramFiles%\*") do (
    
  • Braces ({, }) around the loop body. They are not part of the loop syntax (in fact, they are not part of batch scripting syntax at all), so should be dropped.

  • No closing parenthesis matching the opening one after DO. It should be added on a separate line after the loop body.

  • Incorrect use of ::-style comments in the loop body. They are not allowed inside bracketed blocks. Use REM instead.


UPDATE

In batch scripting, testing for a substring is done somewhat unusually. You'll need another environment variable and you'll also need to enable delayed expansion. The latter is not really connected with the comparison, but it is needed because the comparison is going to be performed within a bracketed block.

Here's your new script modified, with the changes highlighted:

::@echo off
::variables
set AntiVirus1="Initial Value"

IF NOT ERRORLEVEL 0 (echo %ERRORLEVEL%) ELSE echo "env. variable created successfully."

SETLOCAL EnableDelayedExpansion

echo Checking Program Files...
for /d %%f in ("%ProgramFiles%\*") do (
   echo "%%f"
   SET "folder=%%f"
   if /I NOT "!folder:adobe=!"=="!folder!" set AntiVirus1="adobe"
)

echo %AntiVirus1% found

@pause

Here's a bit of explanation.

The ! syntax is a delayed expansion equivalent of % and is used with environment variables only, not with loop variables and not with command line parameters. Delayed expansion is needed because we are in a bracketed block. A bracketed block is parsed entirely before it starts executing, so all %var% expressions are expanded (evaluated) before the block starts and are not changed throughout the block's execution. That cannot suit us because we need to assign different values to a variable during the block's execution, and the values must be read within the block. Delayed expansion, as follows from the name, delays the expansion of a variable until the actual execution of every single command that references that variable. Because immediate expansion can still be used alongside delayed expansion, a different syntax is introduced, which is ! around variable names, instead of %.

!folder:adobe=! means evaluate folder replacing every occurrence of adobe with an empty string. The result of this expression is then compared to the (unchanged) value of folder. If there's a match, then the replacement didn't occur, which means there was no adobe in the value of folder in the first place. In this case we should do nothing. But if there was not a match, i.e. if the modified value didn't match the unmodified one, then we should set the AntiVirus1 variable. This is why there's NOT in front of the comparison.

The /I option simply means case-insensitive comparison.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜