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 :
/i : Comparison is case-insensitive. (ie.
pBat'' will be equal toPBAT’’).
NOT : Negation. The code is ran if string1 and string2 are different.
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:
EQU : (EQUal) string1 and string2 are the same.
NEQ : (Not EQual). Exact opposite of preceeding condition.
LEQ : (Less or EQual). The value associated to string1 is lesser or equal to string2.
LSS : (LeSS). The value associated to string1 is strictly lesser than string2.
GTR : (GreaTeR). The value associated to string1 is strictly greater than string2.
GEQ : (Greater or EQual). The value associated to string1 is greater or equal to string2.
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 :
DEFINED : The condition is true if the variable named by object is defined.
EXIST : The condition is true if a file named by object exists. The string object can contain regulars expressions.
ERRORLEVEL : Deprecated The condition is true if the environment variable %ERRORLEVEL% is greater or equal to object, were object is a number . Its use is deprecated, you should use the following syntax instead :
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.
/i : Discard case-sensitiveness.
[ expression ] : A list of conditions to be met for the code to be executed. The use of brackets and space around elements is mandatory.
An expression should be built made of comparisons connected together with some logical operators.
Two types of tests are available :
[NOT] cmp1 comparison cmp2 [NOT] [Defined|Errorlevel|Exist] objet
Both these forms are the same as those described above.
There is two operators available:
or : Logical or.
and : Logical and.
The and operator own precedence over or operators.
Finally, one can affect precedence using brackets .
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.
my_var can be enclosed in double quotes, avoiding blank characters problem. However, the characters like & and | contained in my_var will still be interpreted, and my_var could not contain double-quotes anymore.
The best solution is to expand my_var using delayed expansion rather than conventional expansion. Indeed, using that trick, my_var will only be expanded after the line parsing, and thus no character can cause issue.
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 )
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