The commands DO (when used with the UNTIL or WHILE keyword), IF, IFF/ELSEIFF, and the variable function @IF evaluate a conditional expression, and perform a different action based on whether or not the expression is TRUE. The SWITCH command tests pairs of values for equality. Most of the examples below use the IF command, but conditional expressions could be used in the other cases above as well.
A conditional expression can be one of the following, as described below:
A relational expression compares two character strings, using one of the relational operators in the table below. Each of these two character strings can contain literal text, environment and internal variables, and variable functions, including user defined ones, in any combination. Note that double quotes are significant.
When comparing the two character strings, either a numeric or a string comparison will be used. A numeric comparison treats the strings as numeric values and tests them arithmetically. A string comparison treats the strings as text. The parser uses the rules described for the @NUMERIC function to determine whether or not the strings are numeric, and only if both are numeric is a numeric comparison performed. If either value is non-numeric, a string comparison is used. To force a string comparison when both values may be numeric, use double quotes around the values you are testing, as shown below. Because the quote mark is not a numeric character, string comparison is performed. Numeric comparison cannot be forced. To compare hexadecimal numbers numerically, you must convert them to decimal numbers using @CONVERT. This is not necessary if both are the same length - string comparison and numeric comparison yield the same result.
The example below demonstrates the difference between numeric and string comparisons, as shown in the table below. Numerically, 2 is smaller, but as a string it is "larger" because its first digit is larger than the first digit of 19. So the first of these conditions will be true, and the second will be false:
expression |
value |
comparison type |
2 lt 19 |
true |
numeric |
"2" lt "19" |
false |
string |
Relational Expression Formats
The format of a relational expression is one of
num1 relational operator num2
string1 relational operator string2
Note: The correct syntax requires a space both before and after operator to separate it from its operands. Commonly seen constructs such as %a==b may or may not work depending on the specific parameters, but they are never recommended.
operator |
numeric comparison: expression is true if |
string comparison: expression is true if, when ignoring character case: |
EQ or == |
num1 equals num2 |
string1 equals string2 |
NE or != |
num1 does not equal num2 |
string1 does not equal string2 |
LT |
num1 is less than num2 |
string1 alphabetically precedes string2 |
LE |
num1 is less than or is equal to num2 |
string1 alphabetically precedes or is equal to string2 |
GE |
num1 is greater than or is equal to num2 |
string1 alphabetically succeeds or is equal to string2 |
GT |
num1 is greater than num2 |
string1 alphabetically succeeds string2 |
EQC |
tested as strings è |
string1 is identical to string2, including character case |
=~ |
regular expression test |
string1 matches the regular expression in string2 |
!~ |
regular expression test |
string1 doesn't match the regular expression in string2 |
Case differences are ignored in string comparisons (except by EQC). If two strings begin with the same text but one is shorter, the shorter string is considered to precede (be less than) the longer one. For example, "a" is less than "abc", and "hello_there" is greater than "hello".
When you compare text strings, you may need to enclose the parameters in double quotes in order to avoid syntax errors which can occur if one of the parameter values is empty (e.g., due to an environment variable which has never been assigned a value). This technique will not work for numeric comparisons, as the quotes will force a string comparison, so with numeric tests you must be sure that all variables are assigned values before the test is done.
In order to maintain compatibility with CMD, TCC recognizes the following additional names for conditions:
CMD |
TCC |
EQL or EQU |
EQ |
NEQ |
NE |
LSS |
LT |
LEQ |
LE |
GTR |
GT |
GEQ |
GE |
Internal variables and variable functions are very powerful when combined with string and numeric comparisons. They allow you to test the state of your system, the characteristics of a file, date and time information, or the result of a calculation. You may want to review the variables and variable functions when determining the best way to set up a condition test.
These conditions test operating system, file system or TCC status. In addition to the tests below, there are many internal variables and variable functions which allow you to test the status of many other parts of the system.
In the descriptions below of the various status tests, the status tests are true if and only if the specified condition is true.
DEFINED variable |
If variable exists in the environment, the expression is true. This is equivalent to testing whether or not variable is nonempty. |
Note: GOSUB variables, array variables, and internal variables do not exist in the environment, so they always fail the DEFINED test. |
|
ERRORLEVEL [relational operator] n |
This test retrieves the exit code of the preceding external program. By convention, programs return an exit code of 0 when they are successful and a non-zero number to indicate an error. The relational operator may be any of those listed above (e.g., EQ, GT). If no operator is specified, the default is GE. The comparison is done numerically. |
Not all programs return an explicit exit code. For programs which do not, the behavior of ERRORLEVEL is undefined. |
|
EXIST filename |
If filename matches a file which exists, the expression is true. You can use wildcards in filename, in which case the expression is true if any file matching the wildcard name exists. filename may include an absolute or relative path. |
WARNING: In Windows the expression will be true if there is either a file or a directory named filename. Use ISFILE or ISDIR instead. |
|
The special filename NUL is commonly used in CMD batch files to test the existence of a directory. The expression exist xxx\NUL is true only if xxx is a directory. |
|
ISALIAS aliasname |
If aliasname is defined as an alias, the expression is true. |
ISAPP appname |
If appname matches the name of an application which is currently running, the expression is true. To match a specific application, you must enter the full pathname of the application. Partial names and wildcards will yield undependable results. Both the short and long filename forms of the name will be checked (see LFN File Searches for details on the correspondence between short and long filenames). |
This test may require DEBUG privilege. |
|
ISBATCH filename |
If the specified filename is a batch file, the expression is true. |
ISDIR path DIREXIST path
|
If the directory specified by path exists, the expression is true. Path may be either absolute or relative. DIREXIST may be used as a synonym for ISDIR. |
ISFILE filename |
If filename matches a file which exists, the expression is true. You can use wildcards in the filename, in which case the expression is true if any file matching the wildcard name exists. ISFILE matches only files, not directories. |
ISFUNCTION name |
If the user-defined function name is loaded, the expression is true. |
ISINTERNAL command |
If command is an active internal command, the expression is true. Commands can be activated and deactivated with the SETDOS /I command. |
ISLABEL label |
If label exists in the current batch file, the expression is true. Labels may be one or more words long. Note that this test has nothing to do with disk partition labels. |
ISLIBRARY name |
If the name is a library function, the expression is true |
ISPLUGIN name |
If name is a plugin variable, function, or command, the expression is true. |
ISREADABLE filename |
If the filename is readable, the expression is true. |
ISSYMLINK filename |
If the file is a symbolic link, the expression is true. |
ISVISIBLE "title" |
If the specified window is visible, the expression is true. (This neans that Windows has set the visibility flag; it does not mean that the window is necessarily visible on the desktop.) |
ISWRITEABLE filename |
If the filename is writeable, the expression is true. |
ISHUNG "title" |
If the specified window is not responding, the expression is true.
|
PLUGIN module |
If the plugin module is loaded, the expression is true. Do not include an extension (i.e., ".dll"), for the module name. |
A logical expression is one of the following:
the unary logical operator NOT (or !) followed by a logical expression
two logical expressions connected by a binary logical operator
Logical operators
operator |
type |
usage |
value is TRUE if |
NOT |
unary |
NOT cond |
cond is FALSE. |
.AND. |
binary |
cond1 .AND. cond2 |
both cond1 and cond2 are TRUE. |
.OR. |
binary |
cond1 .OR. cond2 |
at least one of cond1 and cond2 is TRUE. |
.XOR. |
binary |
cond1 .XOR. cond2 |
one of cond1 and cond2 is TRUE, and the other one is FALSE. |
This example runs a program called DATALOAD if today is Monday or Tuesday (enter this on one line):
if "%_dow" == "Mon" .or. "%_dow" == "Tue" dataload
Test conditions are always scanned from left to right -- there is no implied order of precedence, as there is in some programming languages. You can, however, force a specific order of testing by grouping conditions with parentheses, for example (enter this on one line):
if (%a == 1 .or. (%b == 2 .and. %c == 3)) echo something
Combining logical expressions
Parentheses can be used only when the portion of the expression inside the parentheses contains at least one of the binary logical operators .and., .or., or .xor.. Parentheses on a simple expression which does not combine two or more tests will be taken as part of the string to be tested, and will probably make the test fail. For example, the first of these tests is FALSE, the second is TRUE:
(a == a)
(a == a .and. b == b)
Parentheses may be nested.
This batch file fragment runs a program called WEEKLY if today is Monday:
if "%_dow" == "mon" weekly
This batch file fragment tests for a string value:
input "Enter your selection : " %%cmd
if "%cmd" == "WP" goto wordproc
if "%cmd" NE "GRAPHICS" goto badentry
This example calls GO.BTM if the first two characters in the file MYFILE are GO:
if "%@left[2,%@line[myfile,0]]" == "GO" call go.btm
The first batch file fragment below tests for the existence of A:\JAN.DOC before copying it to drive C (this avoids an error message if the file does not exist):
if isfile a:\jan.doc copy a:\jan.doc c:\
This example tests the exit code of the previous program and stops all batch file processing if an error occurred:
if errorlevel == 0 goto success
echo "External Error; Batch File Ends!"
cancel