【问题标题】:"rd" exits with errorlevel set to 0 on error when deletion fails, etc当删除失败等时,“rd”退出,errorlevel 设置为 0
【发布时间】:2012-06-21 12:01:57
【问题描述】:

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

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

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

为什么?你有什么建议?

【问题讨论】:

    标签: windows batch-file error-handling cmd exit-code


    【解决方案1】:

    哇,这是我看到的第二个 ERRORLEVEL 设置不正确的情况!见File redirection in Windows and %errorlevel%

    解决方法同检测重定向失败。使用|| 运算符在失败时采取措施。

    rd testdir || echo The command failed!
    

    奇怪的是,当您使用 || 运算符时,如果文件夹不为空,则 ERRORLEVEL 会正确设置为 145,如果文件夹不存在,则设置为 2。所以你甚至不需要做任何事情。您可以有条件地“执行”一个注释,然后错误级别将被正确设置。

    rd testdir || rem
    echo %errorlevel%
    

    我认为上面给出了一个完整的画面。但是下面的一系列 cmets 表明,使用/RD /S 时仍然存在潜在问题。 如果父文件夹下的文件或子文件夹被锁定(在父文件夹下的任何级别),则RD /S /Q PARENT && echo removed || echo failed 将打印一条错误消息,但会触发&& 分支而不是|| 分支。非常不幸。如果由于父文件夹本身被锁定而导致命令失败,则|| 将正确触发并设置 ERRORLEVEL。

    通过将 stderr 与 stdout 交换并将结果通过管道传输到 FINDSTR "^",可以在所有情况下检测到故障。如果找到匹配项,则一定有错误。

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

    /q 丢失时,stderr 和 stdout 的交换很重要,因为它允许“你确定(Y/N)吗?”提示在 stderr 上可见,与 stdout 上的错误消息分开。

    【讨论】:

    • 这适用于代码 2 和 145,但在“访问被拒绝”或“该进程无法访问该文件,因为它正被另一个进程使用”的情况下,它只会保持 ERRORLEVEL 不变。 :(
    • 这不适用于我的参数 /s。有人可以证实这一点吗?
    • @Barniferous,这取决于错误。我可以确认@Stefan 的发现。即,rd /q /s tmp && echo OK || echo ERROR !errorlevel! 将打印 “该进程无法访问该文件,因为它正被另一个进程使用。” 然后是“OK”(无错误级别)。不过,其他错误,例如 dbenham 帖子中的 ERROR 2 是正确报告的。复制:打开命令提示符和cd 到一个目录。在另一个命令提示符下,尝试使用 dbenham 的解决方案删除该目录。没有错误级别,但会打印错误...:S。在 Windows 7 上测试。
    • 条件执行 || 根本不起作用,如果内部文件夹被阻止访问 Access is deniedRD 只有 0 退出代码。
    【解决方案2】:

    rd 没有将errorlevel 设置为零 - 它使errorlevel 保持不变:f.e.如果先前的操作以正数结束 errorlevelrd 成功完成,则保持 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:确保不要在检查它不是>= 4 后用set errorlevel=0 重置错误级别,因为此命令会创建一个永久覆盖的环境变量内部错误级别。阅读here
    • 这是 IMO 的最佳解决方案。与其尝试做复杂的变通办法、交换输出和其他尝试检测所有奇怪情况的废话……只需查看目录是否仍然存在;如果是,你有问题。
    猜你喜欢
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-27
    • 1970-01-01
    相关资源
    最近更新 更多