Upon a failed redirection (due to a non-existent file or insufficient file access), the ErrorLevel
value seems not to be set (in the following examples, file test.tmp
is write-protected and file test.nil
does not exist):
>>> (call ) & rem // (reset `ErrorLevel`)
>>> > "test.tmp" echo Text
Access is denied.
>>> echo ErrorLevel=%ErrorLevel%
ErrorLevel=0
>>> (call ) & rem // (reset `ErrorLevel`)
>>> < "test.nil" set /P DUMMY=""
The system cannot find the file specified.
>>> echo ErrorLevel=%ErrorLevel%
ErrorLevel=0
However, as soon as the failed redirection is followed by the conditional concatenation operator ||
, which is querying the exit code, the ErrorLevel
becomes set to 1
, unexpectedly:
>>> (call ) & rem // (reset `ErrorLevel`)
>>> (> "test.tmp" echo Text) || echo Fail
Access is denied.
Fail
>>> echo ErrorLevel=%ErrorLevel%
ErrorLevel=1
>>> (call ) & rem // (reset `ErrorLevel`)
>>> (< "test.nil" set /P DUMMY="") || echo Fail
The system cannot find the file specified.
>>> echo ErrorLevel=%ErrorLevel%
ErrorLevel=1
Interestingly, ErrorLevel
remains 0
when the operator &&
is used:
>>> (call ) & rem // (reset `ErrorLevel`)
>>> (> "test.tmp" echo Text) && echo Pass
Access is denied.
>>> echo ErrorLevel=%ErrorLevel%
ErrorLevel=0
>>> (call ) & rem // (reset `ErrorLevel`)
>>> (< "test.nil" set /P DUMMY="") && echo Pass
The system cannot find the file specified.
>>> echo ErrorLevel=%ErrorLevel%
ErrorLevel=0
ErrorLevel
remains also 0
using the operator &
:
>>> (call ) & rem // (reset `ErrorLevel`)
>>> (> "test.tmp" echo Text) & echo Pass or Fail
Access is denied.
Pass or Fail
>>> echo ErrorLevel=%ErrorLevel%
ErrorLevel=0
>>> (call ) & rem // (reset `ErrorLevel`)
>>> (< "test.nil" set /P DUMMY="") & echo Pass or Fail
The system cannot find the file specified.
Pass or Fail
>>> echo ErrorLevel=%ErrorLevel%
ErrorLevel=0
In case both conditional concatenation operators &&
and ||
appear, ErrorLevel
is set to 1
too (if ||
occurs before &&
, both branches are executed as in the last example, but I think this just because &&
evaluates the exit code of the preceding echo
command):
>>> (call ) & rem // (reset `ErrorLevel`)
>>> (> "test.tmp" echo Text) && echo Pass || echo Fail
Access is denied.
Fail
>>> echo ErrorLevel=%ErrorLevel%
ErrorLevel=1
>>> (call ) & rem // (reset `ErrorLevel`)
>>> (< "test.nil" set /P DUMMY="") || echo Fail && echo Pass
The system cannot find the file specified.
Fail
Pass
>>> echo ErrorLevel=%ErrorLevel%
ErrorLevel=1
So what is the connection between the ErrorLevel
value and the ||
operator, why is ErrorLevel
affected by ||
? Is ||
copying the exit code to ErrorLevel
? Is all this only possible with (failed) redirections, because such are handled before any commands are executed?
Even more strangely, I could not observe the opposite behaviour -- ErrorLevel
being reset to 0
by &&
--, when correctly reverting the test setup (that is, replacing (call )
by (call)
(to set ErrorLevel
to 1
initially), clearing the read-only attribute of file test.tmp
, creating file test.nil
(first line not empty to avoid set /P
to set ErrorLevel
to 1
), and using file extension .bat
rather than .cmd
for testing (to avoid set /P
to reset ErrorLevel
to 0
)).
I observed the described behaviour on Windows 7 and Windows 10.