The line continuation ^
escapes the first character on the next line, so the first &
is treated as a literal and is passed as an argument to falsey
. The second &
is treated as simple command concatenation.
One simple solution to get &&
to be treated as conditional command concatenation is to put the &&
on the line before:
falsey &&^
echo nope
or you could put a space before the &&
falsey ^
&& echo nope
The other option is to use the redirection trick that jeb points out in his linked answer, but I never use that trick.
Regarding your "solution" with quoted "&&"
- you are fooling yourself. It appears to work when falsey fails. But if your command succeeds, then you have trouble:
echo ONE ^
"&&" echo TWO
-- OUTPUT --
C:\test>echo ONE " && " echo TWO
ONE "
'" echo TWO' is not recognized as an internal or external command,
operable program or batch file.
Note that the &&
works because the first "
is escaped, so the &&
is not quoted. If you add a space before the "&&"
echo ONE^
"&&" echo TWO
then you get the following
C:\test>echo ONE "&&" echo TWO
ONE "&&" echo TWO
because now the space is escaped and the "&&"
is quoted.
Regarding your comment, you can ignore those extra spaces - they are an artifact of how the parser displays the line when ECHO is ON. The parser often rearranges the line significantly, but normally it does not affect the outcome.
For example
< nul set test=OK
echo [%test%]
--OUTPUT--
C:\test>set test=OK 0<nul
C:\test>echo [OK]
[OK]
Note how the echoed SET line is completely rearranged. The redirection is compressed and moved to the end of the statement, with a space before the redirection. You might think the space would be included in the assignment, but you can see that it is not :-)
The only time you have might have to worry about the rearrangement is if the command is used in a pipe.
For example:
(set test=OK&call echo [%%^^test%%])|findstr "^"
--OUTPUT--
C:\test>(set test=OK & call echo [%^test%] ) | findstr "^"
[OK ]
You can see that there is a single unwanted extra space that is included in the SET value. This is an artifact of how pipes are implemented - each side is executed in a new CMD.EXE process, and the line gets parsed multiple times. You can see where the space comes from by using %CMDCMDLINE%
to display the command line passed to the left side's cmd.exe.
(set test=OK&call echo [%%^^test%%] %%^^cmdcmdline%%)|findstr "^"
--OUTPUT--
C:\test>(set test=OK & call echo [%^test%] %^cmdcmdline% ) | findstr "^"
[OK ] C:\WINDOWS\system32\cmd.exe /S /D /c" ( set test=OK & call echo [%^test%] %^cmdcmdline% )"
See Why does delayed expansion fail when inside a piped block of code? for more information about many quirks with pipes. In particular, pay attention to the selected answer for a good explanation of what is going on.