ChatGPT解决这个技术问题 Extra ChatGPT

Can I have an IF block in DOS batch file?

In a DOS batch file we can only have 1 line if statement body? I think I found somewhere that I could use () for an if block just like the {} used in C-like programming languages, but it is not executing the statements when I try this. No error message either. This my code:

if %GPMANAGER_FOUND%==true(echo GP Manager is up
goto Continue7
)
echo GP Manager is down
:Continue7

Strangely neither "GP Manager is up" nor "GP Manager is down" gets printed when I run the batch file.

Ya, that helps. DOS sucks. If I want to use multiple statements in if or else I have to use && between statements? or is there a more elegant way?

C
Cody Gray

You can indeed place create a block of statements to execute after a conditional. But you have the syntax wrong. The parentheses must be used exactly as shown:

if <statement> (
    do something
) else (
    do something else
)

However, I do not believe that there is any built-in syntax for else-if statements. You will unfortunately need to create nested blocks of if statements to handle that.


Secondly, that %GPMANAGER_FOUND% == true test looks mighty suspicious to me. I don't know what the environment variable is set to or how you're setting it, but I very much doubt that the code you've shown will produce the result you're looking for.

The following sample code works fine for me:

@echo off

if ERRORLEVEL == 0 (
    echo GP Manager is up
    goto Continue7
)
echo GP Manager is down
:Continue7

Please note a few specific details about my sample code:

The space added between the end of the conditional statement, and the opening parenthesis.

I am setting @echo off to keep from seeing all of the statements printed to the console as they execute, and instead just see the output of those that specifically begin with echo.

I'm using the built-in ERRORLEVEL variable just as a test. Read more here


Better use if %ERRORLEVEL% == 0, as the other variant is always true, because IF ERRORLEVEL is true, if errorlevel is equal or greater , the "==" are ignored in this case
@jeb: I think you might have missed the point. Using ERRORLEVEL is not the answer to his problem. I was simply posting an example of the proper syntax. Either form is acceptable in this case, just as would be if 0 == 0 or any other trivial expression. But indeed, make sure that you understand the difference between the environment variable %ERRORLEVEL% and the internal ERRORLEVEL of the command processor. Raymond Chen explains it nicely here on this blog.
Might be worth noting that if you need to use a path that contains parenthesis (C:\Program Files (x86), for example) inside the IF block then you'll have to use delayed expansion or the IF block will exit as soon as it encounters the parenthesis in the path, as I found out.
Adding to @mythofechelon's comment, even a seemingly innocuous closing parenthesis in a REM statement will end the block. e.g. Throwing REM This is a comment (or so I thought) into the IF block will mess you up.
Both @mythofechelon and @rkagerer are pointing out specific issues of a general rule that strings need to be quoted. You should never code IF %somevar%==example_string2 it should always be code so operand resolve to IF "value_of_somevar"=="example_string2" to avoid special characters in either string operand causing syntax errors in the IF statement. Values you set should always be done as set "somevar=value_of_somevar" That syntax allows you to escape special characters in variable values, Note that I do not mean set somevar="value_of_somevar"
N
Nick

Logically, Cody's answer should work. However I don't think the command prompt handles a code block logically. For the life of me I can't get that to work properly with any more than a single command within the block. In my case, extensive testing revealed that all of the commands within the block are being cached, and executed simultaneously at the end of the block. This of course doesn't yield the expected results. Here is an oversimplified example:

if %ERRORLEVEL%==0 (
set var1=blue
set var2=cheese
set var3=%var1%_%var2%
)

This should provide var3 with the following value:

blue_cheese

but instead yields:

_

because all 3 commands are cached and executed simultaneously upon exiting the code block.

I was able to overcome this problem by re-writing the if block to only execute one command - goto - and adding a few labels. Its clunky, and I don't much like it, but at least it works.

if %ERRORLEVEL%==0 goto :error0
goto :endif

:error0
set var1=blue
set var2=cheese
set var3=%var1%_%var2%

:endif

Using delayed expansion should work: use: set var3=!var1!_!var2!
V
VLL

Instead of this goto mess, try using the ampersand & or double ampersand && (conditional to errorlevel 0) as command separators.

I fixed a script snippet with this trick, to summarize, I have three batch files, one which calls the other two after having found which letters the external backup drives have been assigned. I leave the first file on the primary external drive so the calls to its backup routine worked fine, but the calls to the second one required an active drive change. The code below shows how I fixed it:

for %%b in (d e f g h i j k l m n o p q r s t u v w x y z) DO (
if exist "%%b:\Backup.cmd" %%b: & CALL "%%b:\Backup.cmd"
)

Why on earth is this downvoted? This is exactly what I needed.
@GCB667 - To clarify @Louis" wrote an "answer" that does not relate to the problem of why the IF statement was not working for the original poster. It related to an answer by "vinniejohnson" (that also missed original posters problem).
D
David A. Gray

I ran across this article in the results returned by a search related to the IF command in a batch file, and I couldn't resist the opportunity to correct the misconception that IF blocks are limited to single commands. Following is a portion of a production Windows NT command script that runs daily on the machine on which I am composing this reply.

    if "%COPYTOOL%" equ "R" (
    WWLOGGER.exe "%APPDATA%\WizardWrx\%~n0.LOG" "Using RoboCopy to make a backup of %USERPROFILE%\My Documents\Outlook Files\*"
    %TOOLPATH% %SRCEPATH% %DESTPATH% /copyall %RCLOGSTR% /m /np /r:0 /tee
    C:\BIN\ExitCodeMapper.exe C:\BIN\ExitCodeMapper.INI[Robocopy] %TEMP%\%~n0.TMP %ERRORLEVEL%
) else (
    WWLOGGER.exe "%APPDATA%\WizardWrx\%~n0.LOG" "Using XCopy to make a backup of %USERPROFILE%\My Documents\Outlook Files\*"
    call %TOOLPATH%  "%USERPROFILE%\My Documents\Outlook Files\*" "%USERPROFILE%\My Documents\Outlook Files\_backups" /f /m /v /y
    C:\BIN\ExitCodeMapper.exe C:\BIN\ExitCodeMapper.INI[Xcopy] %TEMP%\%~n0.TMP %ERRORLEVEL%
)

Perhaps blocks of two or more lines applies exclusively to Windows NT command scripts (.CMD files), because a search of the production scripts directory of an application that is restricted to old school batch (.BAT) files, revealed only one-command blocks. Since the application has gone into extended maintenance (meaning that I am not actively involved in supporting it), I can't say whether that is because I didn't need more than one line, or that I couldn't make them work.

Regardless, if the latter is true, there is a simple workaround; move the multiple lines into either a separate batch file or a batch file subroutine. I know that the latter works in both kinds of scripts.


v
vinniejohnson

Maybe a bit late, but hope it hellps:

@echo off 

if %ERRORLEVEL% == 0 (
msg * 1st line WORKS FINE rem You can relpace msg * with any othe operation...
goto Continue1
)
:Continue1
If exist "C:\Python31" (
msg * 2nd line WORKS FINE rem You can relpace msg * with any othe operation...
    goto Continue2
)
:Continue2
If exist "C:\Python31\Lib\site-packages\PyQt4" (  
msg * 3th line WORKS FINE rem You can relpace msg * with any othe operation...
    goto Continue3
)
:Continue3
msg * 4th line WORKS FINE rem You can relpace msg * with any othe operation...
    goto Continue4
)
:Continue4
msg * "Tutto a posto" rem You can relpace msg * with any othe operation...
pause