IF command

The IF command allows conditional processing of commands.

This command is very important for creating advanced batch scripts as it allows script to make conditionnal execution.

You might also prefer multilines IF to IF-GOTO combination, which are a little bit disordered.

Synopsis - First syntax

The very first one just compares two strings, and execute the specified commands if they’re both equal. It supports also some basic modifiers. The syntax is :

 IF [/i] [NOT] string1==string2 (
 :: code to be ran
 ...
 )

Check whether string1 and string2 are the same strings and run the code to be run if it is true. The behaviour can be modified by the following switches and modifiers :

Synopsis - Second syntax

The second syntax is used to compare either strings and numbers. It allows scripts to perform more advanced test such as testing if one number is greater than another one. This syntax should also be prefered since it is more robust, and if well used, this syntax is much more resistant to expansion bugs. As explained later.

 IF [/i] string1 cmp string2 (
 :: code to be ran
 ...
 )

Test comparison specified by cmp to strings string1 and string2 and run the code to be executed if the specified comparison is true.

Where cmp can be one of the following:

LSS, GTR, LEQ and GEQ conditions require string1 and string2 to represent integers otherwise the result is unspecified.

Before attempting any comparisons, the IF command checks if both string1 and string2 can be converted to integers. Strings that can be converted to integers are numbers written either decimal, hexadecimal (in which case the number have to be prefixed with 0x) or octal (which prefix is 0) base. The said integer value must be between -2147483648 and 2147483647. If both string1 and string2 can be converted to integers, IF compares the two integers.

If either string1 or string2 does not meet this criteria, IF checks if string1 and string2 can be converted to floating point. The only syntax authorized for floating point value is of the form value[e][exponant]. If both string1 and string2 can be converted to floats, then IF compares the floats values.

If string1 and string2 cannot be converted, then IF compares string1 and string2. If any of LEQ, LSS, GTR or GEQ comparisons is used, then IF bases comparison on lexicographical order. For example is if string1 is before string2 in lexicographical order, then string1 is considered to be below string2.

To force string comparisons, it is possible to add a prefix to the comparison. For example :

IF x!value1! EQU x!value2! command

Synopsis - Third syntax

The last syntax allows to perform test on a object. Obviously, the specified command are ran if the test performed returned true.

 IF [NOT] [DEFINED | EXIST | ERRORLEVEL] object (
 :: code to be ran
 ...
 )

Checks whether the condition stated about object is true, and then executes the code to be executed if the condition is true. The conditions can be :

If you specify operator NOT, then the code to be executed is ran if the condition is false.

Synopsis - Expressions (Fourth syntax)

pBat offer a fourth syntax for the IF command. This syntax allows using logical connectors to build expressions.

IF [/i] [ expression ] (
 :: code to run
...
)

Run the code if the conditions specified by expression are met.

Synopsis - ELSE subcommand

After any kind of previously described IF, an ELSE keyword may be inserted so that code specified after the ELSE will be ran if the IF comparison fails.

 IF /i %var1%==%var2% (
:: code to be executed if %var1% is equal to %var2%
) ELSE (
:: code to be executed if %var1% differs form %var2%
)

Both ELSE keyword preceeding and following codes must be enclosed in brackets, so that it defines two different code blocks. Otherwise, the interpretor should interpret it like a single line.

Both of these codes will work as expected:

IF /i %var1%==%var2% (
 ECHO %var1% is equal to %var2%
) ELSE (
 ECHO %var1% differs from %var2%
)

IF /i %var1%==%var2% (ECHO %var1% is equal to %var2%) ELSE (ECHO %var1% differs from %var2%)

:: both will output:
::  - ``ECHO %var1% is equal to %var2%''
::    when %var1% is equal to %var2%
:: - ``ECHO %var1% differs from %var2%''
::    when %var1% differs for %var2%

Whereas the following code will fail :

IF /i %var1%==%var2% ECHO %var1% is equal to %var2% ELSE ECHO %var1% differs from %var2%
:: will output
:: ``ECHO %var1% is equal to %var2% ELSE ECHO %var1% differs from %var2%''
:: only when %var1% is equal to %var2%

Dealing with spaces

Almost anyone have already seen the following message output from the prompt :

Error : ``some'' was unexpected.

This error, has two origins. On the one hand, it could be sometimes just caused by a syntax error (ie. prompt is failing to run command because it syntax is incorect). This account for a great part of the causes of this error. On the other hand, the hand that we’re interested in, it could be simply caused by a space character that wasn’t expected. It happens really easy when using var expansion with variable that contain spaces or tabs. Let’s take an example :

IF %my_var%==test (
 ECHO The test is true
)

As long as my_var does not contains any space, or whatever possibly interpreted (such as & and |), this example works pretty well. But, if my_var do contains such characters, it goes wrong. This effect is caused because my_var is expanded before even the line interpretation, thus, any characters from my_var will be interpreted. There’s several trick to fix that bug.

Therefore, if you really need avoiding these errors (for scripts that modify windows registry), for exemple, you should use the most robust solution, ie:

SETLOCAL EnableDelayedExpansion

IF !my_var!==test (
 ECHO The test is true
)

The == bug

The fact that the second syntax is much more resistant to expansion bugs as been stated previously. Indeed, if a script complies to all hints to avoid bugs that have been given previously, it’s still not guaranted to resist to all bugs. Indeed, the first syntax is subject to the ``== bug’’. The following code is subject to this bug

SETLOCAL EnableDelayedExpansion

IF !my_var!==test (
 ECHO The test is true
)

As stated in the previous part, this is perfectly unvunerable to bugs due to spaces, whatever… Nevertheless, a bug is encountered if my_var contains ==''. In this case, the behaviour of comparison is modified as it uses first ==’’ encountered. In most cases, this is issue is not even a problem, because script rarely make a comparison with ``==’’ in both members. But it can cause the comparison to be inconsitent in some cases.

To conclude, if such a scenario is likely to happen when executing script, prefer the following syntax:

SETLOCAL EnableDelayedExpansion

IF !my_var! EQU test (
 ECHO The test is true
)

Compatibility

Compatible with cmd.exe. Indeed, the use of IF ERRORLEVEL is not guaranted to be compatible with cmd.exe, as the behaviour of cmd.exe is weird (it tests if ERRORLEVEL is greater than the specified number) and causes numbers of mistakes.

Supported since version 0.4.

FEQ comparison is supported since version 0.7.0.1

See also

FOR command, GOTO command, CALL command, Command list