9} How can I suppress script error messages altogether?
To
introduce, let's take the example of finding out which drives
are present and read, and which are not.
@echo off & setlocal enableextensions
enabledelayedexpansion
for %%a in (A B C D E F G H I J K L M
N O P Q R S T U V W X Y Z) do (
dir %%a:\
2>&1|findstr /b /i /r /c:" Volume in drive "
>nul
if
!errorlevel
! EQU 0 (
echo Device %%a: found and ready
) else (
echo Device %%a: not found or not ready)
)
endlocal & goto :EOF
C:\_D\TEST>cmdfaq
Device A: not found or not ready
Device B: not found or not ready
Device C: found and ready
Device D: found and ready
Device E: found and ready
Device F: not found or not ready
:
Device Y: not found or not ready
Device Z: found and ready
Compare that with what we would have with the two redirections
2>&1 and
>nul omitted:
@echo off & setlocal enableextensions
enabledelayedexpansion
for %%a in (A B C D E F G H I J K L M
N O P Q R S T U V W X Y Z) do (
dir %%a:\ |findstr /b /i /r /c:" Volume in drive "
if
!errorlevel
! EQU 0 (
echo Device %%a: found and ready
) else (
echo Device %%a: not found or not ready)
)
endlocal & goto :EOF
C:\_D\TEST>cmdfaq
The device is not ready.
Device A: not found or not ready
The system cannot find the path specified.
Device B: not found or not ready
Volume in drive C is SUPU_C
Device C: found and ready
Volume in drive D is SALMI_1GB
Device D: found and ready
Volume in drive E has no label.
Device E: found and ready
The system cannot find the path specified.
Device F: not found or not ready
:
The system cannot find the path specified.
Device Y: not found or not ready
Volume in drive Z is SupuZip20080315
Device Z: found and ready
Having observed the above, let's start from the
basics. This is a classic carryover from UNIX. First consider
@echo off
echo Customized pause, press the anykey ...
pause>nul
The usual pause message goes to the nul bitbucket, and only the
customized message appears (actually before the pause).
When you type
dir *.tex > texlist.dir
you'll get the folder listing into texlist.dir but if there are
any errors, then the error messages are forced on the standard output
device (the screen), not to textlist.dir, while the rest of the output
still goes there. You would have on the screen the message
File Not Found
What if you do not wish to see that message, but redirect it to the
bit bucket. This is the syntax then
dir *.tex > texlist.dir 2>&1
Since the test folder has no *.tex file, a file "File Not Found"
message is produced, but it is redirected to texlist.dir, not to the
screen.
Consider the following cryptic-looking script
@echo off
dir > nul 2>&1
It produces no output. Now why would one wish to do something like
that? ... Because, some commands return an errorlevel, and that is
what one really is after, as is seen from the example which this item
started with.
For example XCOPY returns exit codes as shown by the demonstration
below where "Y:" is a non-existent drive in the test.
For example XCOPY returns exit codes as shown by the demonstration
below where "Y:" is a non-existent drive in the test.
@echo off
xcopy /v *.* Y: > nul
for %%L in (5 4 3 2 1 0) do if errorlevel==%%L (
set level_=%%L
goto _tell
)
:_tell
echo The errorlevel of the operation was %level_%
set level_=
The output produced will be
Invalid drive specification
The errorlevel of the operation was 4
However, change the second line to
xcopy /v *.* Y: > nul 2>&1
and the only output will be just
The errorlevel of the operation was 4
Another example. Assume that there is no disk in the A: drive.
dir a:
will produce
The device is not ready.
However
dir a:>nul 2>&1
will only produce a blank line, but not the error message.
Why 2>&1? Because the numeric equivalent of the STDERR is 2 and the
numeric equivalent of STDOUT handle is 1. This becomes more evident
if you do the following in phases
dir NoSuchFile 2>stderr.tmp
The error message will be directed to stderr.tmp while the rest will
appear on the screen. Then enter
dir NoSuchFile>out.tmp 2>&1
and all the output, the error message included, will go to out.tmp
This item was about suppressing error messages. Another way of
thinking is avoiding the errors, at least in easily expected
situations. Consider
DIR "C:\_M\*.CMD"
which will produce
File Not Found
if no *.CMD files are located in the folder C:\_M. This can be
avoided by instead using either
if exist "C:\_M\*.CMD" dir "C:\_M\*.CMD"
or e.g.
for %%f in ("C:\_M\*.CMD") do echo %%~tf %%~zf "%%~ff"
Below is a demonstration how to play with stderr. The unraveling and
customizing to one's own potential task is left to the reader
@echo off & setlocal enableextensions
for %%f in (stderr.tmp tmp$$$.cmd) do if exist %%f del %%f
set var_=
::
dir cmdfaq.cmd 2>stderr.tmp
::
for /f "tokens=* delims=" %%r in ('
type stderr.tmp') do echo @set var_=%%r>tmp$$$.cmd
if exist tmp$$$.cmd call tmp$$$.cmd
::
if defined var_ (
echo var_=%var_%
) else (
echo var_ is undefined. The DIR command was successful.
)
::
for %%f in (stderr.tmp tmp$$$.cmd) do if exist %%f del %%f
endlocal & goto :EOF
The output (slightly condensed) will be
C:\_D\TEST>cmdfaq
Directory of C:\_D\TEST
var_=File Not Found
Or, if you instead have in the script
dir MyExisting.txt 2>stderr.tmp
the output (again slightly condensed) will be
C:\_D\TEST>cmdfaq
Directory of C:\_D\TEST
16.04.2006 06:36 523 MyExisting.txt
1 File(s) 523 bytes
0 Dir(s) 27 814 150 144 bytes free
var_ is undefined. The DIR command was successful.