该批处理必须从特定位置删除文件和目录,并将成功或 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
一切正常,但没有成功消息。随着这条线的留下,它呼应了每一条线的成功。
最佳答案
del
和 ErrorLevel
?
只要给定的参数有效,del
命令就不会设置 ErrorLevel
,它甚至在这种情况下将 ErrorLevel
重置为 0
(至少对于 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 =)
要直接在命令提示符而不是批处理文件中使用代码,请编写 %#
而不是 %%#
。如果不想删除只读文件,请从
/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 /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
预置 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
来捕获 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)
关于batch-file - 批处理文件和 DEL 错误级别 0 问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22953027/