When can I use && and || syax?

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
evandaviswilliams
Posts: 3
Joined: 10 Sep 2017 15:45

When can I use && and || syax?

#1 Post by evandaviswilliams » 10 Sep 2017 18:07

Hi everyone, first post here on these forums. Been teaching myself Batch for the past month or so :D

Right now, I'm running through Steve Jansen's Batch tutorial here:
http://steve-jansen.github.io/guides/wi ... codes.html

I'm curious about when exactly I can use the && and || syntax, specifically to evaluate the success or failure of batch scripts I've writtten myself.

These seem to work just fine for exe's i.e. "core" Windows commands.

I have the following testing script called ErrorReturn.cmd

Code: Select all

@ECHO OFF
ECHO.
GOTO :MAIN

:MAIN
SETLOCAL EnableExtensions EnableDelayedExpansion
   SET /A errno=0
   CHOICE /C 01 /N /M "Select exiting code [0/1]:"
   SET /A errno=%ERRORLEVEL%-1
ENDLOCAL & EXIT /B %errno%


I basically want to be able to choose 0 for success, 1 for failure at execution time, to play around with && and || syntax with follow-on commands.

When I run the script from the command line...

Code: Select all

ErrorReturn.cmd && ECHO Success
ErrorReturn.cmd || ECHO Failure

...it always seems to succeed with && regardless of what I enter at the CHOICE prompt. That is, the || syntax doesn't trigger a failure even when %ERRORLEVEL% is set to 1 by EXIT /B.

I did a little bit of research to try to figure this out, and there seems to be a distinction between the notion of an ERRORLEVEL, and the actual exit code of a program. Can someone explain to this to me in a bit more detail.

I do notice that when I do...

Code: Select all

%COMSPEC% /C ErrorReturn.cmd && ECHO Success
%COMSPEC% /C ErrorReturn.cmd || ECHO Failure

...I do get the behavior I'm looking for.

Not sure where the /B switch factors into things either? Or if it's just a matter of running a child CMD process? Any explanation of what's going on there would be helpful.

npocmaka_
Posts: 516
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: When can I use && and || syax?

#2 Post by npocmaka_ » 11 Sep 2017 02:23

you can also use call:

Code: Select all

call ErrorReturn.cmd && ECHO Success
call ErrorReturn.cmd || ECHO Failure


or pipe (though this is not the preferable way to do it)

Code: Select all

break| ErrorReturn.cmd && ECHO Success
break| ErrorReturn.cmd || ECHO Failure



The errorlevel is evaluated after the whole line is executed ,because it is in the same context i.e. the whole line is passed to the cmd (including the ErrorReturn.bat/cmd) - it executes it and returns the result.And
With cmd /c the cmd.exe executed the first part returns the errorlevel and the second part is executed. With call a new context/thread of the cmd is created and when it finishes and the flow is returned to the parent context the errorlevel is returned.
If you put the " ErrorReturn.cmd && ECHO Success" in a batch file you'll also not be able to execute anything after that line because of the same reason.

pieh-ejdsch
Posts: 240
Joined: 04 Mar 2014 11:14
Location: germany

Re: When can I use && and || syax?

#3 Post by pieh-ejdsch » 11 Sep 2017 04:13

Hello,
Another command also returns Errorlevel: (call, set /a, find ...)
At the end of your batch, you can write a simple math task that implements the errorlevel.
You do not need an endlocal because it automatically terminates this Batch within all of setlocal.

Code: Select all

@echo off
setlocal
choice /c AB
2>nul set /a E/=(-2+%errorlevel%)

Now CMD will also bring you this Errorlevel:

Code: Select all

D:\ERlevel.cmd && echo yes ||echo NO

Phil

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: When can I use && and || syax?

#4 Post by penpen » 11 Sep 2017 05:15

npocmaka_ wrote:The errorlevel is evaluated after the whole line is executed ,because it is in the same context i.e. the whole line is passed to the cmd (including the ErrorReturn.bat/cmd) - it executes it and returns the result.
That's not the reason why the above doesn't work; counter example:

Code: Select all

@echo off
set "=" 2>nul && echo ok || echo fail
set "a=" 2>nul && echo ok || echo fail

Result:

Code: Select all

Z:\>test.bat
fail
ok


The "return value" (aka "exitcode") and "errorlevel" (aka "process exit code") are two different things:
The return value is just a value function returned by a function when it finished (if stdcall convention is used - which is the default for most windows functions - this is the content of the eax register), while the errorlevel is a value stored in a process context (see line 69: https://source.winehq.org/source/server/process.h).

Any internal/external command is encapsulated within a function and therefore a return code is computed always, while the errorlevel is only updated when running child processes.

The operators "&&" and "||" are checking the return value, so setting the errorlevel doesn't change its behavior directly.
If the command line interpreter instance exits, then it also returns the errorlevel, so "%COMSPEC% /C ErrorReturn.cmd && ECHO Success" works as you expected.
But when you execute "ErrorReturn.cmd && ECHO Success" then return value is set by the return code of the last command executed in the ErrorReturn.cmd (pieh-ejdsch's code uses this fact) which is "EXIT /B %errno%" in your case.
The command "EXIT /B %errno%" seems to always return 0 no matter which errorcode is set or if it is executed successfully:
"test.bat"

Code: Select all

exit /b 1

Result:

Code: Select all

Z:\>cmd /E:OFF
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. Alle Rechte vorbehalten.

Z:\>ec.bat && echo ok || echo false
Das Sprungziel - EOF wurde nicht gefunden.
ok

Z:\>cmd /E:ON
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. Alle Rechte vorbehalten.

Z:\>ec.bat && echo ok || echo false
ok

Z:\>echo %errorlevel%
1


penpen

npocmaka_
Posts: 516
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: When can I use && and || syax?

#5 Post by npocmaka_ » 11 Sep 2017 05:29

Btw .
Why with pipe and conditional execution operator I can create 4 cmd contexts?

echo 1:%cmdcmdline% >&2 && echo 2:%cmdc^mdline% >&2 | echo 3:%cmd^cmdline% & echo 4:%cmdcmdline%

output is:

Code: Select all

1:"cmd.exe" /s /k pushd "C:\test"
2:C:\WINDOWS\system32\cmd.exe  /S /D /c" echo 2:%cmdcmdline%  1>&2"
3:C:\WINDOWS\system32\cmd.exe  /S /D /c" echo 3:%cmdcmdline% "
4:"cmd.exe" /s /k pushd "C:\test"


looks like every line points to a cmd sub-process with a different command line

Edit - looks like the conditional execution operators are with higher prio than the pipe
though this also prints similar result:
(echo 1:%cmdcmdline% >&2 && echo 2:%cmdc^mdline% >&2 )| echo 3:%cmd^cmdline% & echo 4:%cmdcmdline%

evandaviswilliams
Posts: 3
Joined: 10 Sep 2017 15:45

Re: When can I use && and || syntax?

#6 Post by evandaviswilliams » 11 Sep 2017 13:01

npocmaka_ wrote:you can also use call:

Code: Select all

call ErrorReturn.cmd && ECHO Success
call ErrorReturn.cmd || ECHO Failure


With call a new context/thread of the cmd is created and when it finishes and the flow is returned to the parent context the errorlevel is returned.
If you put the " ErrorReturn.cmd && ECHO Success" in a batch file you'll also not be able to execute anything after that line because of the same reason.


That really cleared things up for me, thanks!

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: When can I use && and || syax?

#7 Post by aGerman » 11 Sep 2017 13:05

penpen wrote:The "return value" (aka "exitcode") and "errorlevel" (aka "process exit code") are two different things

Indeed, and you could use them to return different values.
viewtopic.php?f=3&t=5826
(Although it's a little off-topic here. But it shows the difference between exit /b n and cmd /c exit n which is what you explained above.)

Steffen

evandaviswilliams
Posts: 3
Joined: 10 Sep 2017 15:45

Re: When can I use && and || syax?

#8 Post by evandaviswilliams » 11 Sep 2017 13:40

aGerman wrote:
penpen wrote:The "return value" (aka "exitcode") and "errorlevel" (aka "process exit code") are two different things

Indeed, and you could use them to return different values.
viewtopic.php?f=3&t=5826
(Although it's a little off-topic here. But it shows the difference between exit /b n and cmd /c exit n which is what you explained above.)

Steffen


Thanks for the info! Interesting read :)

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: When can I use && and || syax?

#9 Post by penpen » 11 Sep 2017 16:44

npocmaka_ wrote:Btw .
Why with pipe and conditional execution operator I can create 4 cmd contexts?

echo 1:%cmdcmdline% >&2 && echo 2:%cmdc^mdline% >&2 | echo 3:%cmd^cmdline% & echo 4:%cmdcmdline%
The edit indicates, that you've noticed it, but just for completeness - the above example should be equal to the following:

Code: Select all

(echo 1:%cmdcmdline% >&2 &&( echo 2:%cmdc^mdline% >&2 | echo 3:%cmd^cmdline% ))& echo 4:%cmdcmdline%


penpen

Post Reply