del 和 ErrorLevel?
只要给定的参数有效,del 命令就不会设置ErrorLevel,它甚至会在这种情况下将ErrorLevel 重置为0(至少对于Windows 7)。
del 仅在提供无效开关的情况下修改ErrorLevel(del /X 将ErrorLevel 设置为1),根本没有指定任何参数(del 将ErrorLevel 设置为@987654336 @ too),或者给出了不正确的文件路径(del : 将 ErrorLevel 设置为 123),至少对于 Windows 7。
可能的解决方法
一种可能的解决方法是捕获del 的STDERR 输出,因为在删除错误的情况下,相关消息(Could Not Find [...]、Access is denied.、The process cannot access the file because it is being used by another process.)会写入那里。这可能看起来像:
for /F "tokens=*" %%# in ('del /F /Q "\path\to\the\file_s.txt" 2^>^&1 1^> nul') do (2> nul set =)
要直接在命令提示符中而不是在批处理文件中使用代码,请编写 %# 而不是 %%#。
如果您不想删除只读文件,请从 del 命令行中删除 /F;
如果您确实需要提示(如果文件路径中存在通配符? 和/或*),请删除/Q。
代码说明
这将执行命令行del /F /Q "\path\to\the\file_s.txt"。通过2>&1 1> nul 部分,STDOUT 的命令输出将被解除,其STDERR 输出将被重定向,以便for /F 接收它。
如果删除成功,del 不会生成STDERR 输出,因此for /F 循环不会迭代,因为没有要解析的内容。注意ErrorLevel 在这种情况下不会被重置,它的值保持不变。
如果for /F从del命令行接收到任何STDERR输出,则执行循环体中的命令,即set =;这是一个无效的语法,因此set 将ErrorLevel 设置为1。 2> nul 部分避免显示消息 The syntax of the command is incorrect.。
要显式设置ErrorLevel,您还可以使用cmd /C exit /B 1。也许这条线更清晰。当然它更灵活,因为您可以声明任何(带符号的 32 位)数字,包括 0 来清除它(省略数字也会清除它)。不过在性能方面可能会差一些。
应用示例
以下批处理文件演示了如何应用上述解决方法:
:DELETE
echo Deleting "%~1"...
rem this line resets ErrorLevel initially:
cmd /C exit /B
rem this line constitutes the work-around:
for /F "tokens=*" %%# in ('del /F /Q "C:\Users\newuser\Desktop\%~1" 2^>^&1 1^> nul') do (2> nul set =)
rem this is the corrected ErrorLevel query:
if not ErrorLevel 1 echo Deleted "%~1" succesfully.
goto :EOF
预设ErrorLevel
除了上面提到的命令cmd /C exit /B,你还可以使用> nul ver来重置ErrorLevel。这可以与for /F 循环解决方法结合使用,如下所示:
> nul ver & for /F "tokens=*" %%# in ('del /F /Q "\path\to\the\file_s.txt" 2^>^&1 1^> nul') do (2> nul set =)
没有for /F 的替代方法
除了使用for /F 来捕获del 的STDERR 输出之外,还可以使用find 命令,如find /V "",如果出现空字符串,则返回ErrorLevel 的1在和0 否则:
del "\path\to\the\file_s.ext" 2>&1 1> nul | find /V "" 1> nul 2>&1
但是,如果删除成功,这将返回 ErrorLevel 或 1,否则返回 0。为了扭转这种行为,可以像这样附加一个if/else 子句:
del "\path\to\the\file_s.ext" 2>&1 1> nul | find /V "" 1> nul 2>&1 & if ErrorLevel 1 (1> nul ver) else (2> nul set =)
不同的方法:在del 之后检查文件是否存在
一种完全不同的方法是在尝试删除文件后检查文件是否存在(感谢用户Sasha 提供hint!),例如:
del /F /Q "\path\to\the\file_s.txt" 1> nul 2>&1
if exist "\path\to\the\file_s.txt" (2> nul set =) else (1> nul ver)