in DOS batch files, In an IF
statement, is it possible to combine two or more conditions using AND or OR ? I was not able to find any documentation for that
As long as command extensions are enabled, you can use compare-operators.
This is directly pasted from "help if":
If Command Extensions are enabled IF changes as follows:
IF [/I] string1 compare-op string2 command
IF CMDEXTVERSION number command
IF DEFINED variable command
where compare-op may be one of:
EQU - equal
NEQ - not equal
LSS - less than
LEQ - less than or equal
GTR - greater than
GEQ - greater than or equal
and the /I switch, if specified, says to do case insensitive string compares. The /I switch can also be used on the string1==string2 form of IF. These comparisons are generic, in that if both string1 and string2 are both comprised of all numeric digits, then the strings are converted to numbers and a numeric comparison is performed.
AND:
IF <COND1> IF <COND2> ACTION
OR:
(SET _=) & (IF <COND1> (SET _= ) ELSE IF <COND2> (SET _= )) & IF DEFINED _ ACTION
For implementing OR this way, you do need command extensions.
I sometimes wonder, what people learn at school nowadays! Of course 'OR' is possible too. Any system that can provide you with a 'NOT' and an 'AND', automatically provides you with an 'OR' too, because:
x OR y = NOT ( (NOT x) AND (NOT y) ) see http://en.wikipedia.org/wiki/De_Morgan%27s_laws
So as long as the expression "if (x AND y) then do z" can be written like this:
if (x) if (y) (do z)
... we should be able to write the expression "if (x OR y) then do z", but there is a problem:
Where shall we put the first 'NOT'? Well, the answer is nowhere, we should reform the equation above first to:
NOT ( x OR y ) = (NOT x) AND (NOT y)
According to this, we may write "if (NOT(x OR y)) then (do z)" as:
"if ((NOT x) AND (NOT y)) then (do z)"
Having this and knowing how to express AND as shown above, we can now write the expression "if (NOT(x OR y)) then (do z)" as:
if (not x) if (not y) (REM do z)
We also know that the expression:
"if (NOT p) then (do q) else (do r)"
... is equivalent to:
"if (p) then (do r) else (do q)
Thus we can write for "if (x OR y) then (do z)":
"if (NOT(x OR y)) then (do nothing) else (do z)"
So we can express "if (x OR y) then (do z)" as:
if (not x) if (not y) (REM do nothing) else (REM do z)
But this is not complete yet, because this is not a true 'AND' but a "simulated" one. What is missing is the second else. So the complete form to get the correct result should be:
if (not x) ( if (not y) (REM do nothing) else (REM do z) ) else (REM do z) )
... which has the ugly double else part. You can solve that with a 'goto' and we finally have:
rem if (x OR y) then (do z):
if (not x) ( if (not y) (goto :doNothing) )
rem do z
:doNothing
No, there is no easier way.
For and
you can also just chain them without introducing blocks:
if COND1 if COND2 ...
which frankly isn't any worse than
if COND1 and COND2 ...
However, for or
it gets uglier, indeed:
set COND=
if COND1 set COND=1
if COND2 set COND=1
if defined COND ...
or:
if COND1 goto :meh
if COND2 goto :meh
goto :meh2
:meh
...
:meh2
I once saw a batch preprocessor which used C-like syntax for control flow and batch stuff in between and then converted such conditionals into multiple jumps and checks. However, that thing was for DOS batch files and was of little to no use in a Windows environment.
For the AND workaround I agree with Joey, I cannot see another solution.
For the OR workaround I would propose the following 'trick':
Lets say that you want to test if user asked for help on the command line while calling for your batch file, something like: thebatch /?
.
But you don't know if the user will type /?
or rather (being a Unix accustomed user) --help
or -h
or even forget to pass any argument at all.
Your code could be like:
for %%P in ("" "-h" "--help") do if "%1"==%%P (
:help
echo this is my help... >&2
exit /b 9
)
Note however that testing "/?" or "-?" strings won't work with that trick (FOR
loops don't like the ?
meta character).
For that purpose, just add the line: if "%1"=="/?" goto help
on top of the block (see the ':help'
label inside the for
loop ?)
Note too that this syntax won't work (it is just completely ignored and code won't be executed) with batch files under TCC.EXE (the Take Command interpreter, either full or lite edition) but in that case just use their syntax with their .OR.
and .AND.
keywords.
Hope this helps.
If your conditions are checking for specific values of a variable, you might be able to set it up like a CASE statement. I had a need to check if the TYPE was an individual member or a group (or all).
Note: labels are case insensitive.
If any of the conditions are true (if TYPE==ALL
or TYPE==GROUP1
or TYPE==GROUP2
), then the code block executes, otherwise execution skips over the block.
goto :TYPE_EQ_%TYPE% 2>NUL
if %ERRORLEVEL% neq 0 goto :END_CASE_TYPE
:TYPE_EQ_ALL
:TYPE_EQ_GROUP1
:TYPE_EQ_GROUP2
rem do what you need
echo GROUP: %TYPE%
:END_CASE_TYPE
I don't like Mehrdad's Electrical Engineering (digital electronics) approach. While accurate, with software engineering, the idea, as indicated by the OP, is to make things simpler to figure out. Nested if statements add Complexity (McCabe). Adding extra NOTs doesn't help.
My solution is a little odd if you don't know the goto-label/error set-up, but it's a flat structure that is roughly set up like an if-statement with several OR'd conditions that are not to hard to decipher.