“rd” exits with errorlevel set to 0 on error when deletion fails, etc

后端 未结 2 676
温柔的废话
温柔的废话 2020-11-27 21:03

I\'m writing a batch (.bat) script and I need to handle the case in which the deletion of a folder fails. I\'m using %errorlevel% to catch the exit code, but in

相关标签:
2条回答
  • 2020-11-27 21:32

    Wow, this is the 2nd case I've seen where ERRORLEVEL is not set properly! See File redirection in Windows and %errorlevel%.

    The solution is the same as for detecting redirection failure. Use the || operator to take action upon failure.

    rd testdir || echo The command failed!
    

    The bizarre thing is, when you use the || operator, the ERRORLEVEL is then set properly to 145 if the folder was not empty, or 2 if the folder did not exist. So you don't even need to do anything. You could conditionally "execute" a remark, and the errorlevel will then be set properly.

    rd testdir || rem
    echo %errorlevel%
    

    I thought the above gave a complete picture. But then a series of comments below demonstrated there are still potential problems when /RD /S is used. If a file or subfolder under the parent folder is locked (at any level under parent) then RD /S /Q PARENT && echo removed || echo failed will print out an error message, but the && branch fires instead of the || branch. Very unfortunate. If the command fails because the parent folder itself is locked, then || will properly fire and set the ERRORLEVEL.

    It is possible to detect failure in all cases by swapping stderr with stdout and piping the result to FINDSTR "^". If a match is found, then there must have been an error.

    3>&2 2>&1 1>&3 rd /s test | findstr "^" && echo FAILED
    

    The swap of stderr and stdout is important when /q is missing because it allows the "Are you sure (Y/N)?" prompt to be visible on stderr, separate from the error message on stdout.

    0 讨论(0)
  • 2020-11-27 21:38

    rd does not set errorlevel to zero - it leaves errorlevel intact: f.e. if previous operation ends in positive errorlevel and rd finishes successfully it leaves errorlevel unchanged. Example: error levels of robocopy below 4 are warnings and not errors and can be ignored so the following code may end with error even when the directory was deleted successfully:

    robocopy ...
    if errorlevel 4 goto :error
    rd somedir
    if errorlevel 1 goto :error
    

    Solution: ignore the error and check if the directory still exists after rd:

    rd somedir
    if exist somedir goto :error
    
    0 讨论(0)
提交回复
热议问题