File redirection in Windows and %errorlevel%

The command

type nul > C:\does\not\exist\file.txt

invoked with a non-existent path is terminated at redirection failure and type is not invoked at all. It therefore has no chance of setting ERRORLEVEL. The redirection, being performed by the shell, does not set ERRORLEVEL.

One solution is to pre-initalise ERRORLEVEL with a non-zero value. It will remain unchanged upon failure and will be reset to zero (by type) upon success:

@echo off
::pre-initialise ERRORLEVEL with a value of 1:
call :SETERROR 1
type NUL > NOSUCHDIR\test.txt
IF ERRORLEVEL 1 goto ERROR
echo All is well.
goto END
:ERROR
echo Error detected.
:END
goto :eof
:SETERROR
exit /b %1

The shorft form

type NUL > NOSUCHDIR\test.txt && goto OK || goto ERROR

works because it analyses exit code, which is not the same as error level:

An exit code can be detected directly with redirection operators (Success/Failure ignoring the ERRORLEVEL) this can often be more reliable than trusting the ERRORLEVEL, which may or may not have been set correctly.

Herbert Kleebauer explained this to me in the Usenet group alt.msdos.batch.

Update:
An anonymous user suggested an alternative solution based on the COPY command:

COPY NUL: C:\does\not\exist\file.txt

This command does set ERRORLEVEL, which may be analysed by the next command in the script. Very convenient, so I thank him for the proposed edit.


You can use the following:

C:\>type nul > C:\does\not\exist\file.txt && echo ok || echo fail
The system cannot find the path specified.
fail

C:\>echo %errorlevel%
1

I always assumed the && and || operators used ERRORLEVEL, but apparently not.

Very curious that ERRORLEVEL is set after redirection error only if you use the || operator. I never would have guessed. Nor would I ever have bothered to test if not for your excellent question.

If all you want to do is set the ERRORLEVEL upon redirection failure, then of course you can simply do:

type nul > C:\does\not\exist\file.txt || rem