批处理文件和DEL errorlevel 0问题

Joh*_*ott 2 batch-file echo errorlevel delete-file delete-directory

批处理必须从特定位置删除文件和目录,并将成功或stdout/stderr消息输出到新的.txt文件.我创建了大部分脚本,它完全按预期执行,除非删除成功,它会向前移动到下一行,而不是在日志上回显"成功"消息.

echo Basic Deletion Batch Script > results.txt
@echo off
call :filelog >> results.txt 2>&1
notepad results.txt
exit /b

:filelog

call :delete new.txt
call :delete newer.txt
call :delete newest.txt
call :remove c:\NoSuchDirectory

GOTO :EOF

:delete
echo deleting %1
del /f /q c:\Users\newuser\Desktop\%1 
if errorlevel 0 echo succesful

GOTO :EOF

:remove
echo deleting directory %1
rmdir /q /s %1

GOTO :EOF
Run Code Online (Sandbox Code Playgroud)

由于某种原因,我无法找到if del success echo'success'的语法.在上面的示例中,如果我删除该行

if errorlevel 0 echo successful
Run Code Online (Sandbox Code Playgroud)

一切正常,但没有成功的消息.留下这条线就可以说明每一条线的成功.

asc*_*pfl 9

del和ErrorLevel?

只要给定的参数有效,该del命令就不会设置ErrorLevel,它甚至ErrorLevel会0在这种情况下重置to (至少对于Windows 7).

del修改ErrorLevel仅在情况下的无效开关设置(del /X集ErrorLevel到1),没有参数在所有指定(del设置ErrorLevel到1太),或不正确的文件路径被给予(del :设置ErrorLevel到123),至少为Windows 7.

可能的解决方法

一个可能的解决办法是捕捉到STDERR的输出del,因为在删除错误的情况下,相关的消息(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 =)
Run Code Online (Sandbox Code Playgroud)

要直接在命令提示符中而不是在批处理文件中使用代码,请编写%#而不是%%#.

如果您不想删除只读文件,/F请del从命令行中删除;
如果您确实需要提示(如果通配符?和/或*存在于文件路径中),请删除/Q.

代码说明

这将执行命令行del /F /Q "\path\to\the\file_s.txt".通过该部分2>&1 1> nul,命令输出at STDOUT将被解除,并且其STDERR输出将被重定向以便for /F接收它.

如果删除成功,del则不生成STDERR输出,因此for /F循环不会迭代,因为没有要解析的内容.请注意,ErrorLevel在这种情况下不会重置,其值保持不变.

如果从命令行for /F接收任何STDERR输出,del则执行循环体中的命令,即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
Run Code Online (Sandbox Code Playgroud)

预置 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 =)
Run Code Online (Sandbox Code Playgroud)

替代方法没有 for /F

而不是使用for /F捕捉到STDERR的输出del,该find命令也可以使用像find /V "",它返回ErrorLevel的1,如果一个空字符串进来,1否则:

del "\path\to\the\file_s.ext" 2>&1 1> nul | find /V "" 1> nul 2>&1
Run Code Online (Sandbox Code Playgroud)

然而,这将返回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 =)
Run Code Online (Sandbox Code Playgroud)


fox*_*ive 2

当使用这个语法时,而不是这个

if errorlevel 0 echo successful
Run Code Online (Sandbox Code Playgroud)

你可以使用这个 - 因为错误级别 0 总是 true。

if not errorlevel 1 echo successful
Run Code Online (Sandbox Code Playgroud)