"rd"在删除失败时以错误级别0退出,等等。

9 浏览
0 Comments

"rd"在删除失败时以错误级别0退出,等等。

我正在编写一个批处理(.bat)脚本,我需要处理删除文件夹失败的情况。我使用%errorlevel%来捕获退出代码,但在rd命令的情况下似乎不起作用:

C:\Users\edo\Desktop>rd testdir

目录不是空的

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

0

为什么?你有什么建议吗?

0
0 Comments

"rd"命令在删除失败时,错误级别设置为0的原因是出现了不同的情况。解决方法是使用"||"操作符在失败时执行操作。

问题的出现原因是,当使用"||"操作符时,如果文件夹不为空,则错误级别正确地设置为145,如果文件夹不存在,则错误级别设置为2。因此,您甚至不需要做任何操作。您可以有条件地执行一个备注,错误级别将被正确设置。

解决方法是使用"||"操作符在失败时执行操作。

如果在父文件夹下的文件或子文件夹被锁定(在父级下的任何级别),则"RD /S /Q PARENT && echo removed || echo failed"将打印出错误消息,但是"&&"分支会触发而不是"||"分支。非常不幸。如果命令失败是因为父文件夹本身被锁定,则"||"将正确触发并设置错误级别。

可以通过交换stderr和stdout,并将结果传输到"FINDSTR "^"来检测所有情况下的失败。如果找到匹配项,则肯定发生了错误。

当缺少"/q"时,交换stderr和stdout非常重要,因为它允许在stderr上显示"Are you sure (Y/N)?"提示,与stdout上的错误消息分开。

这个解决方法对于代码2和145很好用,但是对于"Access denied"或"文件因为被其他进程使用而无法访问"的情况下,它只会保持错误级别不变。

该方法在Windows 10上不起作用。有人能证实吗?

这种情况对于参数"/s"对我来说不起作用。有人可以确认吗?

它取决于错误的类型。我可以确认's的发现。例如,"rd /q /s tmp && echo OK || echo ERROR !errorlevel!"将打印出"The process cannot access the file because it is being used by another process.",然后打印出"OK"(没有错误级别)。其他错误,如dbenham的帖子中的ERROR 2则被正确报告。在命令提示符下打开并cd到一个目录。在另一个命令提示符中,尝试使用dbenham的解决方案删除该目录。没有错误级别,但是错误被打印出来。

如果内部文件夹被阻止访问,则条件执行"||"根本不起作用。"RD"只有0的退出代码。

我想上面提到的来自的示例仅适用于"Access Denied"情况,因为它是非递归删除。它是关于"junk"目录本身的"Access denied",而不是关于它的内部。如果"Access denied"是由目录中的某个文件引起的,则错误级别为0。我认为这可能是因为"del"的错误函数(stackoverflow.com/questions/22953027/…)。也许在递归删除期间,Windows尝试使用"del"删除目录中的每个文件,并且不幸地始终返回0。

我想起了POSIX的"rm -f"(强制删除)的行为,它不仅在尽可能的范围内忽略权限,而且还抑制错误代码,始终退出0。我认为这是为了使清理操作尽可能健壮,特别是在使用"set -e"(如在Makefile的配方中)时。显然,在配方中,命令行前缀加上减号可以达到相同的结果。也许"cmd"对"rd"和"del"的处理是出于类似的动机。

0
0 Comments

rd命令在删除失败时,不会将errorlevel设置为0,而是保持不变。例如,如果前一个操作以正的errorlevel结束,并且rd成功完成,它将保持errorlevel不变。例如,robocopy的错误级别低于4是警告而不是错误,可以忽略,所以下面的代码即使目录成功删除也可能以错误结束:

robocopy ...

if errorlevel 4 goto :error

rd somedir

if errorlevel 1 goto :error

解决方法是:忽略错误并在rd之后检查目录是否仍然存在:

rd somedir

if exist somedir goto :error

还有关于robocopy的问题:确保在检查errorlevel不大于4后,不要使用set errorlevel=0重置errorlevel,因为这个命令会创建一个永久覆盖内部errorlevel的环境变量。在这里阅读更多信息。

这是我认为最好的解决方法。不要试图做复杂的变通方法,交换输出或其他垃圾来检测所有奇怪的情况...只需检查目录是否仍然存在;如果存在,则表示存在问题。

0