批处理文件和DEL errorlevel 0问题

时间:2014-04-09 04:50:48

标签: batch-file echo delete-file errorlevel delete-directory

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

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

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

if errorlevel 0 echo successful

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

8 个答案:

答案 0 :(得分:7)

delErrorLevel

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

ErrorLevel仅在提供无效切换的情况下修改del /XErrorLevel1设置为del),根本不指定任何参数( ErrorLevel也将1设置为del :,或者提供了错误的文件路径(ErrorLevel123设置为STDERR),至少Windows 7。

可能的解决方法

可能的解决方法是捕获del的{​​{1}}输出,因为如果删除错误,相关消息(Could Not Find [...]Access is denied.,{{ 1}})写在那里。这可能看起来像:

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设置为ErrorLevel1部分避免显示消息2> nul

要明确设置The syntax of the command is incorrect.,您还可以使用ErrorLevel。也许这条线更清晰。确保它更灵活,因为您可以声明任何(带符号的32位)数字,包括cmd /C exit /B 1以清除它(省略数字也会清除它)。但是在性能方面可能会有点差。

应用示例

以下批处理文件演示了如何应用上述解决方法:

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的{​​{1}}输出,STDERR命令也可以像del一样使用,它返回find 1}} find /V ""如果有空字符串,则为ErrorLevel

1

但是,如果删除成功,这将返回1 del "\path\to\the\file_s.ext" 2>&1 1> nul | find /V "" 1> nul 2>&1 ,如果没有,则返回ErrorLevel。要扭转这种行为,可以像这样附加1 / 0子句:

if

答案 1 :(得分:1)

使用此语法时,而不是此

if errorlevel 0 echo successful

你可以使用它 - 因为errorlevel 0总是为真。

if not errorlevel 1 echo successful

答案 2 :(得分:1)

只需使用UnxUtils(或gowcygwin)中的rm。如果文件不存在或删除文件时出现任何错误,它将正确设置错误级别。

答案 3 :(得分:0)

到目前为止,我记得正确的语法是:

if %errorlevel% == 0 echo succesful

百分号是检查环境变量的暗示。

答案 4 :(得分:0)

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

我发现了怎么做......无论如何都是这样。

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

答案 5 :(得分:0)

如果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

OR

: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

答案 6 :(得分:0)

aschipfl 的答案很棒(非常感谢,帮了我很多忙!)使用 Presetting ErrorLevel 下的代码,你得到了一个很好的标准函数:

请注意在AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier; 语句中使用%~1代替%1,否则如果使用带引号的文件名,则会出错。

del

BTW 1:你可以给出一个漂亮的错误信息作为第二个参数
顺便说一句2:使用::###################################################################### ::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 代替::进行评论会使代码更具可读性。

答案 7 :(得分:0)

代码:

错误代码: (您所做的事情)

if errorlevel 0 echo succesful

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

正确的代码: (此处应为实际内容。)

if %ERRORLEVEL% EQU 0 echo succesful

定义:

EQU: EQU代表Equal。这种运算符也称为关系运算符。如果您想了解更多信息,请点击documentation链接到运营商,还有其他链接,但这对我有所帮助。


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

%foo%

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