Programming Field

If - DOS/Command Prompt Reference

Performs conditional processing in batch files.

Syntax

Use one of following 7 syntaxes (the fourth and later are Extensions syntaxes).

if [not] errorlevel <number> <command-line> [else <command-line>]
if [not] exist <file-name> <command-line> [else <command-line>]
if [not] <string1>==<string2> <command-line> [else <command-line>]
if /I [not] <string1>==<string2> <command-line> [else <command-line>]
if [/I] [not] <string1> <operator> <string2> <command-line> [else <command-line>]
if [not] defined <variable-name> <command-line> [else <command-line>]
if [not] cmdextversion <number> <command-line> [else <command-line>]

Options

not Determines whether the following condition is ‘not applicable’ (‘false’). By using not, the latter command (<command-line>) is executed in case of ‘not applicable’.
errorlevel <number> Checks the exit code returned by previous program (commands). Specifies the number to <number>. If the exit code is greater than or equal to <number>, <command-line> is executed.
exist <file-name>

Checks whether the specified file exists. Specifies the file name to <file-name> (can include drive/path). If the file <file-name> exists, <command-line> is executed.

Please note that the behavior when <file-name> is a directory (i.e. determining whether the directory exists) is OS-dependent.

<string1>==<string2>

Checks whether two strings are equal. Specifies strings to <string1> and <string2>. Usually, specifies an environment variable (by using ‘%’) to either or both placeholders to check its value. If <string1> and <string2> are equal, <command-line> is executed.

Comparison of strings is case sensitive. And, quotation marks on the strings are not necessary. You can use space characters before and after ‘==’ (does not affect to comparison). Please see also Compare strings.

[MS-DOS, Windows 95/98/Me] Even if surrounding with quotation marks, commas ‘,’, equal signs ‘=’, and semicolons ‘;’ cannot be included in strings (<string1> and <string2>).

<command-line>

Specifies a command to execute when the condition is met. The command can include environment variables and batch parameters.

[Windows NT series] The command can be divided to multiple lines by using ‘( )’. However, a sequence of commands is processed as one command, meaning that expansions of all ‘%’ within ( ) are processed first.

else <command-line>

[Windows NT series] Specifies a command to execute when the condition is not met (or when the condition is met if not is specified). The command can include environment variables and batch parameters.

‘( )’ can be used for <command-line> just after else, but if ‘( )’ is used before else, ‘else’ must immediately follow the closing parenthesis and space. (Please see details below.)

/I [Windows NT series] [Extensions] When comparing strings with ‘==’ or following <operator>, sets the strings to be case insensitive.
<operator> [Windows NT series] [Extensions] Specifies an operator to compare (including ‘==’). Note that if both <string1> and <string2> only include numbers, comparison is performed as a numeric comparison; otherwise comparison is performed as a string comparison.
EQUChecks whether <string1> and <string2> are equal
NEQChecks whether <string1> and <string2> are not equal
LSSChecks whether <string1> is less than <string2>
LEQChecks whether <string1> is less than or equal to <string2>
GTRChecks whether <string1> is greater than <string2>
GEQChecks whether <string1> is greater than or equal to <string2>
defined <variable-name> [Windows NT series] [Extensions] Checks whether an environment variable named ‘<variable-name>’ exists. If the environment variable <variable-name> exists, <command-line> is executed. Specifies an environment variable name without ‘%’ characters to <variable-name> (case insensitive).
cmdextversion <number>

[Windows NT series] [Extensions] Checks whether the Command Extensions version (the value of CMDEXTVERSION environment variable) is larger than or equal to ‘<number>’.

If Extensions are disabled, the condition is always false, resulting the command is not executed. (In MS-DOS and Windows 95/98/Me this syntax is invalid and an error occurs.)

Details

Usage of If

This command is commonly used to perform conditional execution in batch files (Goto is often used in <command-line>). Since this command itself performs conditional branches, Goto is not always necessary when an execution command is only one or etc.

errorlevel

The exit code comparison by errorlevel is determined by whether the value is greater than or equal to specified value, so to check some exit codes, it is necessary to check the exit codes in ascending numerical order. For example,

if errorlevel 1 goto label1
if errorlevel 2 goto label2
if errorlevel 3 goto label3
if errorlevel 4 goto label4
.
.
.

... this program will jump to label ‘label1’ if the exit code is not 0 (1 or larger), even if 1 or 4. So the correct program is as follows:

if errorlevel 4 goto label4
if errorlevel 3 goto label3
if errorlevel 2 goto label2
if errorlevel 1 goto label1
.
.
.

A typical program sets the exit code to 0 when it exits normally (there are exceptions such as Choice), so writing ‘if errorlevel 1 goto OnError’ can handle errors in most cases.

[Windows NT series] A negative value can also be used for errorlevel checks.

[Windows NT series] [Extensions] If Extensions are enabled, by using following string comparison syntax instead of above syntax, the exit code can be compared with ‘ERRORLEVEL’ environment variable. For example the program will be as follows:

rem jump when the exit code is 2
if "%ERRORLEVEL%"=="2" goto label2
rem jump when the exit code is 1 or less
if "%ERRORLEVEL%" LEQ "1" goto label0_1
.
.
.

exist

exist checks whether the file exists. Even if the file is hidden or a system-attribute file, this command can determine whether to exist.

Note that whether ‘exist’ can check for the existence of the directory differs between Windows 95 and XP or later. (To test this, for example, type ‘if exist C:\WINDOWS echo ok’. If ‘ok’ is printed, ‘exist’ can be used for directories.)

By using NUL file, the existence of the directory (and whether the path is a directory) can be checked in all MS-DOS, Windows 9x, and Windows NT series (including XP and later).

if exist X:\Hoge\NUL echo ok

This command will print ‘ok’ if ‘X:\Hoge’ exists as a directory. (If ‘X:\Hoge’ does not exist, or is not a directory, ‘echo ok’ will not be executed.)

Compare strings

Strings comparison is often used for check of environment variable values or batch program parameters. Values of environment variables and parameters can be retrieved by using ‘%’ (e.g. if the environment variable TEMP then ‘%TEMP%’, if ‘the second parameter’ then ‘%2’ ← see also Shift), so these would be specified in <string1> and/or <string2>.

As described above, quotation marks are not necessary. Please see also the following code:

if "test"=="test" echo 1
if "test==test" echo 2
if test"==test" echo 3
if !test==!test echo 4
if !%1==!hello echo 5

For this code, printed numbers are 1, 3, and 4. And, if ‘hello’ is specified as a batch program's parameter (i.e. %1 contains hello), the number 5 is also printed.

However, in case of environment variable value comparison, quotation marks (or another characters or symbols) are necessary if its environment variable is empty. This is because specifying nothing for strings to compare causes a syntax error. For example:

if %foo%==foo echo ok

... this program causes a syntax error if the environment variable ‘foo’ is empty. To prevent this,

rem -- either of followings are ok
if "%foo%"=="foo" echo ok
if $%foo%==$foo echo ok

... it is necessary to write like above.

* Similarly, quotation marks or another are necessary to check whether the string is empty.

Compare with operators

[Windows NT series] [Extensions] The operators such as ‘LSS’ and ‘GEQ’, as well as ‘==’, enable to compare strings or numerics and to control following process (see ‘Syntax’ for operators). If both values are number, the numeric comparison is performed, but either or both values are not number, the alphabets are compared for greater or lesser lexicographic order. However, if ‘/I’ is specified, the comparison is performed in case insensitive, and if equal, performed as ‘lowercase is less than uppercase’.

* How order comparing non alphabets and non numbers is unknown.

rem -- prints 1: strings are equal
if "aaa" EQU "aaa" echo 1
rem -- does not print 2: only uppercase and lowercase do not match
if "aaa" EQU "Aaa" echo 2
rem -- prints 3: ‘/I’ is specified and only uppercase and lowercase do not match
if /i "aaa" EQU "Aaa" echo 3
rem -- does not print 4: strings are equal and compare operator is ‘less than’
if "aaa" LSS "aaa" echo 4
rem -- does not print 5: strings are not equal, compare operator is ‘less than’, and ‘a’ < ‘b’
if "aba" LSS "aaa" echo 5
rem -- prints 6: strings are not equal, compare operator is ‘less than’, and ‘ab’ < ‘ba’ (applying lexicographic order)
if "aba" LSS "baa" echo 6
rem -- prints 7: strings are not equal, compare operator is ‘less than’, and ‘b’ < ‘c’
if "aab" LSS "aac" echo 7
rem -- prints 8: strings are not equal, compare operator is ‘less than’, and only uppercase and lowercase do not match (‘a’ < ‘A’)
if "aaa" LSS "Aaa" echo 8
rem -- does not print 9: compare operator is ‘less than’ and prefer letter differences over upper/lower case 1 (‘A’ < ‘b’)
if "baa" LSS "Aaa" echo 9
rem -- does not print 10: compare operator is ‘less than’ and prefer letter differences over upper/lower case 2 (‘Aa’ < ‘ab’)
if "aba" LSS "Aaa" echo 10
rem -- does not print 11: only integers are treated as ‘numeric values’ (decimals are not recognized)
if "1" EQU "1.0" echo 11

In this sample 1, 3, 6, 7, and 8 are printed.

else

[Windows NT series] ‘else’ is used to execute commands both if the condition is met or not. ‘else’ must be in the same line for ‘if’ keyword, but the command line must ‘end with end-of-line or block termination’, so ‘( )’ are necessary to write.

if /i "%~1"=="/delete" (del mydata.dat) else (echo Not deleted.)

(Without ‘( )’, the command line after ‘quot;%~1"=="/delete"’ is treated as ‘del mydata.dat else echo Not deleted.’.)

Others

[Windows NT series] To execute multiple commands instead of one when the condition is met, surround with ‘( )’ in multiple lines. For example:

if "test"=="test" (
    echo 1
    echo 2
)

... this program prints ‘1’ and ‘2’ across two lines. Note that all environment variable expansions, including variables inside parentheses, are performed before If processings, so please be careful if Set is used inside parentheses (please see also Setlocal page and ‘!’ page).

When using else, else must be written just after the first closing parentheses. A newline cannot be written after closing parentheses. (the entire ‘( )’ is treated as one (non-new-lined) <command-line>.)

if "test"=="test" (
    echo 1
    echo 2
) else (
    echo 3
    echo 4
)

Samples

Sample 1 (Batch file)

@echo off
:Begin
echo Insert CD which includes file MySetup.ini into E drive.
echo After inserting CD, press any key.
echo To cancel, press Ctrl+C.
pause > NUL
if exist E:\MySetup.ini goto Finish
echo MySetup.ini not found.
goto Begin
:Finish

This is a batch file that does not exit until a CD including MySetup.ini is inserted into E drive (assume CD drive is E).

Sample 2 (Batch file)

@echo off
foo.exe "%1"
if "%errorlevel%"=="255" echo Fatal error has occurred.
if "%errorlevel%"=="23" echo Something wrong with '%1'.

[Windows NT series] [Extensions] Executes the program foo.exe with batch program's first parameter, and checks its exit code with string comparison. ‘If errorlevel’ syntax only compares the exit code with ‘greater than or equal to’, but by using ERRORLEVEL environment variable, that is a part of Extensions in Windows NT series, the exit code can be compared with ‘equal to’.

* For samples of If errorlevel, please see Choice command.

* In MS-DOS and Windows 95/98/Me, or the prompt environment that Extensions are disabled, ERRORLEVEL environment variable cannot be used, so ‘If errorlevel’ syntax must be used. In this case, please be careful not to malfunction when judging ‘more than or equal to’, by knowing all exit codes returned by the program.

Sample 3 (Batch file)

@echo off
setlocal enabledelayedexpansion
set MY_COUNTER=1

:main
bar.exe "%1"
if %errorlevel%==0 (
    echo Program was exited successfully.
    exit /b 0
)
if %MY_COUNTER% lss 3 (
    set /a MY_COUNTER="MY_COUNTER+1"
    echo Program returned the error code %errorlevel%. Retrying... (!MY_COUNTER! times)
    goto main
)
echo Program returned the error code %errorlevel%. Exiting.
exit /b %errorlevel%

[Windows NT series] [Extensions] Executes the program bar.exe with batch program's first parameter, and checks its exit code. If the execution fails, and ‘MY_COUNTER’ value is less than 3, increments MY_COUNTER value, prints how many times the next execution is, and executes bar.exe again. If the execution fails and ‘MY_COUNTER’ contains 3, the batch program exits with the exit code value equal to the program's exit code.

In this sample, the command executed when the condition is met in If is specified with multiple lines by using ‘( )’. In this case, to use ‘MY_COUNTER’ value correctly, uses Setlocal and ‘!’ characters. If ‘%MY_COUNTER%’ is used instead of ‘!MY_COUNTER!’, one less value would be printed.

See also