4

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

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

4

7 回答 7

17

delErrorLevel

只要给定的参数有效,该del命令就不会设置,它甚至会在这种情况下将 重置为(至少对于 Windows 7 而言)。ErrorLevelErrorLevel0

delErrorLevel仅在提供无效开关(del /X设置ErrorLevel1)、根本没有指定参数(del设置ErrorLevel1太)或给出不正确的文件路径(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"。通过 part 2>&1 1> nul,命令输出STDOUT将被解除,其STDERR输出将被重定向以便for /F接收它。

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

如果从命令行接收到for /F任何STDERR输出,则执行循环体中的命令,即; 这是无效的语法,因此将 设置为。该部分避免显示消息。delset =setErrorLevel12> nulThe 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 verErrorLevelfor /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输出,如果输入一个空字符串,则返回一个of ,否则:delfindfind /V ""ErrorLevel10

del "\path\to\the\file_s.ext" 2>&1 1> nul | find /V "" 1> nul 2>&1

但是,如果删除成功,如果没有成功,这将返回一个ErrorLevelof 。为了扭转这种行为,可以像这样附加一个/子句:10ifelse

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提示!),例如:

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)
于 2015-10-28T23:41:41.727 回答
1

使用此语法时,而不是 this

if errorlevel 0 echo successful

您可以使用它 - 因为错误级别 0 始终为真。

if not errorlevel 1 echo successful
于 2014-04-09T05:48:38.213 回答
1

只需使用rmUnxUtils gowcygwin)。如果文件不存在或删除文件出现任何错误,它会正确设置错误级别。

于 2018-10-15T22:46:10.123 回答
0

这是原始提问者作为编辑添加的,我已将其转换为社区 wiki 答案,因为它应该是答案,而不是编辑。

我发现了如何做到这一点......无论如何都是一种方式。

echo Startup > 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
dir c:\users\newuser\Desktop\%1  >NUL 2>&1
SET existed=%ERRORLEVEL%
del /f /q c:\Users\newuser\Desktop\%1 
dir c:\users\newuser\Desktop\%1 2>NUL >NUL
if %existed% == 0 (if %ERRORLEVEL% == 1  echo "successful" )

GOTO :EOF

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

GOTO :EOF
于 2015-06-24T16:30:44.607 回答
0

IF ERRORLEVEL 0 [cmd] 每次都会执行,因为 IF ERRORLEVEL # 检查 ERRORLEVEL 的值是否大于或等于 #。因此,每个错误代码都会导致执行[cmd]。

一个很好的参考是:http ://www.robvanderwoude.com/errorlevel.php

>IF /?
Performs conditional processing in batch programs.

IF [NOT] ERRORLEVEL number command
IF [NOT] string1==string2 command
IF [NOT] EXIST filename command

  NOT               Specifies that Windows should carry out
                    the command only if the condition is false.

  ERRORLEVEL number Specifies a true condition if the last program run
                    returned an exit code equal to or greater than the number
                    specified.

我建议将您的代码修改为以下内容:

:delete
echo deleting %1
del /f /q c:\Users\newuser\Desktop\%1 
if errorlevel 1 (
    rem This block executes if ERRORLEVEL is a non-zero
    echo failed
) else (
    echo succesful
)

GOTO :EOF

如果您需要处理多个 ERRORLEVEL 的东西,您可以执行以下操作:

:delete
echo deleting %1
del /f /q c:\Users\newuser\Desktop\%1 
if errorlevel 3 echo Cannot find path& GOTO :delete_errorcheck_done
if errorlevel 2 echo Cannot find file& GOTO :delete_errorcheck_done
if errorlevel 1 echo Unknown error& GOTO :delete_errorcheck_done
echo succesful
:delete_errorcheck_done

GOTO :EOF

或者

:delete
echo deleting %1
del /f /q c:\Users\newuser\Desktop\%1 
goto :delete_error%ERRORLEVEL% || goto :delete_errorOTHER

:delete_errorOTHER
echo Unknown error: %ERRORLEVEL%
GOTO :delete_errorcheck_done
:delete_error3
echo Cannot find path
GOTO :delete_errorcheck_done
:delete_error2
echo Cannot find file
GOTO :delete_errorcheck_done
:delete_error0
echo succesful
:delete_errorcheck_done

GOTO :EOF
于 2015-09-22T01:38:06.300 回答
0

代码:

错误代码:( 你做了什么)

if errorlevel 0 echo succesful

这里的问题是您没有将 errorlevel 作为变量调用,而且您也没有将运算符添加到语句中。

正确的代码:( 实际上应该是这样的。)

if %ERRORLEVEL% EQU 0 echo succesful

定义:

EQU: EQU 代表相等。这种运算符也称为关系运算符。如果您想了解更多,这里是操作员的文档链接,还有其他的,但这对我有帮助。


ERRORLEVEL:被声明为变量,通常获取最后一个命令运行的错误级别。变量通常在像这样的百分号之间时被调用

%foo%

有关变量的更多帮助,请转到 cmd(您可以通过在 Windows 10 上搜索它来访问)并输入“set /?”,不带引号。set 命令是用于设置变量的命令

于 2020-06-21T16:19:09.830 回答
0

aschipfl的答案很棒(谢谢,帮了我很多!)使用Presetting ErrorLevel下的代码,您将获得一个不错的标准函数:

注意在语句中使用%~1而不是,否则如果使用带引号的文件名,则会出错。%1del

::######################################################################
::call :DELETE "file.txt"
::call :DELETE "file.txt" "error message"
:DELETE
  >nul ver && for /F "tokens=*" %%# in ('del /F /Q "%~1" 2^>^&1 1^> nul') do (2>nul set =) || (
    if NOT .%2==. echo %~2
  )
goto :EOF

BTW 1:您可以提供一个漂亮的错误消息作为第二个参数
BTW 2:使用::而不是REM注释使代码更具可读性。

于 2017-03-30T16:29:05.887 回答