The batch has to remove files and directories from specific locations and output success or stdout/stderr messages to a new .txt file. I have created the most of the script and it performs exactly as it should, except when the deletion is successful it moves forward to the next line rather than echo a 'successful' message on the log.
echo Basic Deletion Batch Script > results.txt
@echo off
call :filelog >> results.txt 2>&1
notepad results.txt
exit /b
:filelog
call :delete new.txt
call :delete newer.txt
call :delete newest.txt
call :remove c:\NoSuchDirectory
GOTO :EOF
:delete
echo deleting %1
del /f /q c:\Users\newuser\Desktop\%1
if errorlevel 0 echo succesful
GOTO :EOF
:remove
echo deleting directory %1
rmdir /q /s %1
GOTO :EOF
For some reason I can't find the syntax for if del succeeds echo 'successful'. In the above example if I remove the line
if errorlevel 0 echo successful
Everything works fine, but no success message. With this line left in it echoes success for every line.
This was added as an edit by the original asker, I have converted it to a community wiki answer because it should be an answer, not an edit.
I found out how to do it... one way anyway.
Just use 'rm' command from the UnxUtils (or gow) tools for windows. It sets the errorlevel correctly in case of any errors deleting the file.
When using this syntax, instead of this
you can use this - because errorlevel 0 is always true.
del
andErrorLevel
?The
del
command does not set theErrorLevel
as long as the given arguments are valid, it even resets theErrorLevel
to0
in such cases (at least for Windows 7).del
modifies theErrorLevel
only in case an invalid switch is provided (del /X
setsErrorLevel
to1
), no arguments are specified at all (del
setsErrorLevel
to1
too), or an incorrect file path is given (del :
setsErrorLevel
to123
), at least for Windows 7.Possible Work-Around
A possible work-around is to capture the
STDERR
output ofdel
, because in case of deletion errors, the related messages (Could Not Find [...]
,Access is denied.
,The process cannot access the file because it is being used by another process.
) are written there. Such might look like:To use the code in command prompt directly rather than in a batch file, write
%#
instead of%%#
.If you do not want to delete read-only files, remove
/F
from thedel
command line;if you do want prompts (in case wildcards
?
and/or*
are present in the file path), remove/Q
.Explanation of Code
This executes the command line
del /F /Q "\path\to\the\file_s.txt"
. By the part2>&1 1> nul
, the command output atSTDOUT
will be dismissed, and itsSTDERR
output will be redirected so thatfor /F
receives it.If the deletion was successful,
del
does not generate aSTDERR
output, hence thefor /F
loop does not iterate, because there is nothing to parse. Notice thatErrorLevel
will not be reset in that case, its value remains unchanged.If
for /F
recieves anySTDERR
output from thedel
command line, the command in the loop body is executed, which isset =
; this is an invalid syntax, thereforeset
sets theErrorLevel
to1
. The2> nul
portion avoids the messageThe syntax of the command is incorrect.
to be displayed.To set the
ErrorLevel
explicitly you could also usecmd /C exit /B 1
. Perhaps this line is more legible. For sure it is more flexible because you can state any (signed 32-bit) number, including0
to clear it (omitting the number clears it as well). It might be a bit worse in terms of performance though.Application Example
The following batch file demonstrates how the above described work-around could be applied:
Presetting
ErrorLevel
Besides the above mentioned command
cmd /C exit /B
, you can also use> nul ver
to reset theErrorLevel
. This can be combined with thefor /F
loop work-around like this:Alternative Method Without
for /F
Instead of using
for /F
to capture theSTDERR
output ofdel
, thefind
command could also be used likefind /V ""
, which returns anErrorLevel
of1
if an empty string comes in and1
otherwise:However, this would return an
ErrorLevel
of1
in case the deletion has been successful and0
if not. To reverse that behaviour, anif
/else
clause could be appended like this:IF ERRORLEVEL 0 [cmd] will execute every time because IF ERRORLEVEL # checks to see if the value of ERRORLEVEL is greater than or equal to #. Therefore, every error code will cause execution of [cmd].
A great reference for this is: http://www.robvanderwoude.com/errorlevel.php
I would recommend modifying your code to something like the following:
If you need something that processes more than one ERRORLEVEL, you could do something like this:
OR
As far I remember the correct syntax is:
That percent signs are a hint to check environment variables.