5. Conditionals with if¶
What & why¶
if is how a script makes decisions. Batch's if is limited and quirky: string comparison is the default, quoting matters enormously, and there are special forms for files, variables and exit codes.
String comparison¶
Always quote both sides. If answer is empty, if %answer%==yes becomes if ==yes → The syntax of the command is incorrect. Quoting makes it if ""=="yes" → cleanly false.
== is the only string operator with that spelling. There is no !=; negate with if not:
Case-insensitive¶
Numeric comparison¶
| Operator | Meaning |
|---|---|
EQU |
equal |
NEQ |
not equal |
LSS |
less than |
LEQ |
less than or equal |
GTR |
greater than |
GEQ |
greater than or equal |
Warning
These do a numeric comparison only when both sides look like numbers; otherwise they fall back to string comparison. if "10" GTR "9" is true numerically, but if "10" GTR "9 " (trailing space) compares as strings and is false. Keep both sides clean and unquoted for numeric intent: if %a% LSS %b%.
if exist — files and folders¶
if exist "C:\logs\app.log" echo The log exists.
if not exist "%~dp0config.ini" (
echo Missing config next to script.
exit /b 1
)
rem A trailing \ tests for a directory specifically:
if exist "C:\logs\" echo C:\logs is a folder.
if exist "folder\*" is another way to test a non-empty folder.
if defined — variables¶
Use if defined instead of if "%var%"=="" — it's cleaner and it works with delayed expansion (if defined arr[%i%]).
if errorlevel — exit codes¶
if errorlevel N means "exit code is N or greater." So if errorlevel 1 catches any failure. To test for exactly one value, use %errorlevel%:
Check them in order high-to-low if you branch on several:
More on this in Intermediate Lesson 4.
Blocks, else, and the parenthesis trap¶
The else must be on the same line as the closing ):
This is a syntax error:
Inside ( ... ) blocks, %var% is expanded once, when the block is parsed — not as it runs. This breaks counters and loop bodies. The fix is delayed expansion, Intermediate Lesson 1. For now, keep if blocks simple.
Chaining conditions¶
There is no if A and B. Nest, or use flags:
if "%user%"=="admin" if "%mode%"=="write" echo Allowed.
rem "or" via a helper flag:
set "ok="
if "%ext%"==".jpg" set "ok=1"
if "%ext%"==".png" set "ok=1"
if defined ok echo It's an image.
Common mistakes¶
- Unquoted comparison with a possibly-empty value → syntax error.
elseon its own line →else was unexpected at this time.if errorlevel 0is always true (every code is ≥ 0). Useif %errorlevel% equ 0orif not errorlevel 1.==with surrounding spaces:if "%x%" == "y"— the spaces become part of neither side here, that's actually fine, butif %x%==%y%without quotes and with spaces around values is not. Prefer quoted, no spaces around==.if /iposition: the/igoes right afterif, before the first operand.- Testing a directory with
if exist name— works, but add a trailing\to be sure it's a folder not a file.
Exercises¶
- Prompt for a password; if it equals
hunter2, printAccess granted, elseAccess deniedandexit /b 1. - Accept a number as
%1. Print whether it is negative, zero, or positive usingLSS/EQU/GTR. - Check whether
%~dp0notes.txtexists; if not, create it withecho.>"%~dp0notes.txt"and printCreated. - Accept
%1; if it's empty, print usage andexit /b 1; if/iequal to--help, print help; otherwise echo it back. - Run
findstr xyz nul(which fails), then branch onif errorlevel 1. - FizzBuzz for
%1: useset /aandifwith%%to printFizz,Buzz,FizzBuzz, or the number.
Recap¶
- Quote both sides:
if "%a%"=="%b%". Negate withif not. Case-insensitive withif /i. - Numeric:
EQU NEQ LSS LEQ GTR GEQ— keep operands clean numbers. if exist "path"(trailing\for folders),if defined VAR,if errorlevel N(means ≥ N).elsesits on the)line.%var%inside( )is expanded at parse time — a real gotcha.
Next: Loops with for →