简体   繁体   English

当删除失败等时,“rd”退出时错误级别设置为 0

[英]"rd" exits with errorlevel set to 0 on error when deletion fails, etc

I'm writing a batch (.bat) script and I need to handle the case in which the deletion of a folder fails.我正在编写一个批处理 (.bat) 脚本,我需要处理文件夹删除失败的情况。 I'm using %errorlevel% to catch the exit code, but in the case of the rd command it seems not to work:我正在使用%errorlevel%来捕获退出代码,但在rd命令的情况下,它似乎不起作用:

C:\Users\edo\Desktop>rd testdir
Directory is not empty

C:\Users\edo\Desktop>echo %errorlevel%
0

Why?为什么? What do you suggest?你有什么建议?

Wow, this is the 2nd case I've seen where ERRORLEVEL is not set properly!哇,这是我见过的 ERRORLEVEL 设置不正确的第二个案例! See File redirection in Windows and %errorlevel% .请参阅Windows 中的文件重定向和 %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.如果文件夹不为空,则 ERRORLEVEL 将正确设置为 145,如果文件夹不存在,则设置为 2。 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.但是下面的一系列评论表明,在使用/RD /S时仍然存在潜在问题。 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如果父文件夹下的文件或子文件夹被锁定(在父文件夹下的任何级别),则RD /S /Q PARENT && echo removed || echo failed RD /S /Q PARENT && echo removed || echo failed will print out an error message, but the && branch fires instead of the || RD /S /Q PARENT && echo removed || echo failed将打印出一条错误消息,但是&&分支而不是||会触发branch.分支。 Very unfortunate.很不幸。 If the command fails because the parent folder itself is locked, then ||如果命令因为父文件夹本身被锁定而失败,则|| will properly fire and set the ERRORLEVEL.将正确触发并设置 ERRORLEVEL。

It is possible to detect failure in all cases by swapping stderr with stdout and piping the result to FINDSTR "^" .通过将 stderr 与 stdout 交换并将结果传送到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)?"/q丢失时,stderr 和 stdout 的交换很重要,因为它允许“你确定(是/否)吗?” prompt to be visible on stderr, separate from the error message on stdout.提示在 stderr 上可见,与 stdout 上的错误消息分开。

rd does not set errorlevel to zero - it leaves errorlevel intact: fe if previous operation ends in positive errorlevel and rd finishes successfully it leaves errorlevel unchanged. rd不会将errorlevel设置为零 - 它使errorlevel保持不变:fe 如果之前的操作以正errorlevel结束并且rd成功完成,则它使errorlevel保持不变。 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:示例:低于 4 的robocopy错误级别是警告而不是错误,可以忽略,因此即使目录已成功删除,以下代码也可能以错误结尾:

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后目录是否仍然存在:

rd somedir
if exist somedir goto :error

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM