该批处理必须从特定位置删除文件和目录,并将成功或 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

出于某种原因,我找不到如果 del 成功 echo 'successful' 的语法。在上面的示例中,如果我删除该行
if errorlevel 0 echo successful

一切正常,但没有成功消息。随着这条线的留下,它呼应了每一条线的成功。

最佳答案

delErrorLevel
只要给定的参数有效,del 命令就不会设置 ErrorLevel,它甚至在这种情况下将 ErrorLevel 重置为 0(至少对于 Windows 7)。del 仅在提供无效开关( ErrorLeveldel /X 设置为 ErrorLevel )、未指定任何参数( 1 也将 del 设置为 ErrorLevel )或给出了不正确的文件路径( 1 设置为 del : )、ErrorLevel 时修改 123至少对于 Windows 7。
可能的变通方法
一种可能的解决方法是捕获 STDERRdel 输出,因为在删除错误的情况下,相关消息( 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 =)
要直接在命令提示符而不是批处理文件中使用代码,请编写 %# 而不是 %%#
如果不想删除只读文件,请从 /F 命令行中删除 del
如果您确实需要提示(如果文件路径中存在通配符 ? 和/或 *),请删除 /Q
代码说明
这将执行命令行 del /F /Q "\path\to\the\file_s.txt" 。通过 2>&1 1> nul 部分,STDOUT 处的命令输出将被解除,其 STDERR 输出将被重定向,以便 for /F 接收它。
如果删除成功,del 不会生成 STDERR 输出,因此 for /F 循环不会迭代,因为没有要解析的内容。注意 ErrorLevel 在这种情况下不会被重置,它的值保持不变。
如果 for /FSTDERR 命令行收到任何 del 输出,则执行循环体中的命令,即 set = ;这是无效的语法,因此 setErrorLevel 设置为 12> 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 命令也可以像 STDERR 一样使用,而不是使用 del 来捕获 findfind /V "" 输出,如果传入空字符串,则返回 ErrorLevel1 ,否则返回 0 :
del "\path\to\the\file_s.ext" 2>&1 1> nul | find /V "" 1> nul 2>&1
但是,如果删除成功,这将返回 ErrorLevel1 ,否则返回 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 之后检查文件是否存在
一种完全不同的方法是在尝试删除文件后检查文件是否存在(感谢用户 Sashahint !),例如:
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)

关于batch-file - 批处理文件和 DEL 错误级别 0 问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22953027/

10-13 04:21