0

If I use these commands this way around, it does what it should:

If foo was previously set as one thing or another, it skips to foobar_menu

If foo was previously not set as (the same) one thing or another, it skips to another_menu

rem Check if foo was previously set as bar1 or bar2...
if "%foo%"=="bar1" goto :foobar_menu
if "%foo%"=="bar2" goto :foobar_menu

rem Check if foo was NOT previously set as bar1 or bar2...
if not "%foo%"=="bar1" goto :another_menu
if not "%foo%"=="bar2" goto :another_menu

Here's why it's confusing me - if I swap those around like shown below, then it doesn't work properly, it goes to the wrong label, but why?

rem Check if foo was NOT previously set as bar1 or bar2...
if not "%foo%"=="bar1" goto :another_menu
if not "%foo%"=="bar2" goto :another_menu

rem Check if foo was previously set as bar1 or bar2...
if "%foo%"=="bar1" goto :foobar_menu
if "%foo%"=="bar2" goto :foobar_menu

Why are these two things not doing the same thing?

Is this because I am not putting the goto parts in brackets?

I do have it working (the first way) but that's not the same order my menus go in and I just wanted it all running the way it's laid out in the 2nd (non-working) example above.

Cheers.

EDIT:

These are the actual commands. When put this way around, although nested, it's still going to the label choose_audio_sample_rate even though opus or libopus is set under the variable.

if not "%audio_codec%"=="libopus" if not "%audio_codec%"=="opus" goto :choose_audio_sample_rate
if "%audio_codec%"=="libopus" if "%audio_codec%"=="opus" goto :choose_audio_sample_rate_opus

In fact, the swapped version also doesn't work, it also goes to choose_audio_sample_rate even though opus or libopus is set under the variable.

if "%audio_codec%"=="libopus" if "%audio_codec%"=="opus" goto :choose_audio_sample_rate_opus
if not "%audio_codec%"=="libopus" if not "%audio_codec%"=="opus" goto :choose_audio_sample_rate

I'm turning into a lunatic here lol, OK it will just work (and pass straight to the non-opus menu) if I only use this:

if "%audio_codec%"=="libopus" (goto :choose_audio_sample_rate_opus)
if "%audio_codec%"=="opus" (goto :choose_audio_sample_rate_opus)

If it is libopus, it goes to the the right label. If it's not libopus, the next line gets processed and if it's opus, it goes to the the right label.

If it got beyond that, neither was libopus or opus and it carries on to the general menu.

1
  • well, in the first block, if foo1 == bar1, it doesn't matter what foo2 has as its value, its already branching to foobar_menu. if not, but foo2==bar2, then the same will happen. only if neither condition is true, will it branch to another_menu. in the second block both foo1 == bar1 and foo2==bar2 in order to pass the two NOT checks, and then be evaluated by the check for foo1==bar1. in effect, the first block is an OR relationship between foo1 and foo2, and the second block is an AND relationship, where both foo1 and foo2 must have the desired values, or else you will branch into another_menu. Commented Apr 21, 2021 at 4:25

3 Answers 3

2

Your batch file executes from the top down.

In the second example, even if foo2 or foo1 is set, it’s always going to go to :another_menu. The only way the batch file will move past those two statements is if both foo1 and foo2 are set.

You are essentially creating a logical OR situation.

If foo1 OR foo2 is not set go to another_menu

ELSE

If foo1 OR foo2 is set go to foobar_menu

ELSE

Do nothing

Whereas the first example,

If foo1 OR foo2 is set go to foobar_menu

ELSE

If foo1 OR foo2 is not set go to another_menu

ELSE

Do nothing

What you need is specifically a logical AND. Batch file IF statements do not support either AND or OR. So, we nest them or chain them like so:

if not "%foo1%"=="bar1" if not "%foo2%"=="bar2" goto :another_menu

This says, If foo1 is not set then if foo2 is not set goto :another_menu

Or, more easily, If foo1 AND foo2 are not set goto another_menu

8
  • I just don't get it and don't think I ever will. I didn't post the question as well as I could. I ticked your answer assuming it's right even though I can't grasp what's going on. I still think both ways should do the same thing. It's not checking if the variable was set, they are always set as something - it's checking what it's set as. It's for checking codecs, if %audio_codec% is opus or libopus, goto an opus sample rate menu. if %audio_codec% is not opus or libopus, goto a general sample rate menu
    – bat_cmd
    Commented Apr 21, 2021 at 4:35
  • clearly both ways will not do the same thing. take that at least from this experience. the whole example is poor, because it is using more than one variable, but then is only checking one condition at a time instead of both (a compound if statement, with an AND or an OR) before making a routing decision. keep at it and I'm sure it will come to you. Commented Apr 21, 2021 at 4:45
  • @bat_cmd but, your code does not say “if %audio_codec% is not opus or libopus goto a general sample rate menu.” It says, “if %audio_codec% is not opus goto a general sample rate menu, or if %audio_codec% is not libopus go to a general sample rate menu.” There is a clear difference between those two statements. If the first half is true, the second half will NEVER be evaluated. Commented Apr 21, 2021 at 4:50
  • I have edited the question because it was over-complicating things with foo1/foo2 when they should be the same variable. All the same logic still applies, with the first set of commands working and the second going to the wrong label.
    – bat_cmd
    Commented Apr 21, 2021 at 4:50
  • 1
    @bat_cmd no, only the first line has to be used. In the second group you WANT a logical OR. The different is the NOT. Boolean logic can be confusing. I recommend studying up on it. “If not or if not” means a lot different than “if or if.” You want, “if not and if not” in the first case and “if or if” in the second case. Make sense? Commented Apr 21, 2021 at 12:41
1

Your logic can be simplified a bit through the use of findstr

 Echo("%foo%"|Findstr /C:"bar1" /C:"bar2" > nul && Goto :FooBarMenu || Goto :AnotherMenu

The logic: Findstr compares the string %foo% against bar1 and bar2. If there is a match, the command completes succesfully and conditional operator && executes the following command. If there is no match, || conditional operator is triggered executing the following command, as the preceeding command was not executed succesfuly.

Example:

@Echo off
 Set "foo=notbar"

:loop
 Echo("%foo%"|Findstr /C:"bar1" /C:"bar2" > nul ^
 && Call :fooBarMenu foobarMenu || Call :AnotherMenu Anothermenu
 If not defined foo Exit /B 0
Goto :loop

:foobarmenu
 Echo(@ %~1 foo = %foo%
 Set "foo="
Exit /B 0

:Anothermenu
 Echo(@ %~1 foo = %foo%
 Set "foo=bar2"
Exit /B 0
1

You already checked for bar1 and bar2. So there is no need to check again if it ISN'T bar1 or bar2 (it definitively isn't when the code flow reaches this point because you already branched elsewhere when it did).

rem Check if foo was previously set as bar1 or bar2...
if "%foo%"=="bar1" goto :foobar_menu
if "%foo%"=="bar2" goto :foobar_menu
rem no need to check if foo was NOT previously set as bar1 or bar2
rem if FOO is anything other than the previously checked values, 
rem your code will continue here anyway.
echo FOO isn't bar1 or bar2.
rem Don't forget to end this branch of your code or it will just continue to run:
goto :eof
:foobar_menu
echo reached foobar.

You might want to consider using the /i switch with if to ignore capitalization
(if "foo"=="FOO" is false, if /i "foo"=="FOO" is true)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .