批处理必须从特定位置删除文件和目录,并将成功或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
由于某种原因,我无法找到if del success echo'success'的语法。在上面的示例中,如果我删除该行
if errorlevel 0 echo successful
一切正常,但没有成功的消息。留下这条线就可以说明每一条线的成功。
del
and 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
的1
,如果空字符串进来,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
一种完全不同的方法是在尝试删除文件后检查文件是否存在(感谢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)
!),例如:
if errorlevel 0 echo successful
使用此语法时,而不是此
if not errorlevel 1 echo successful
你可以使用它 - 因为errorlevel 0始终为true。
rm
到目前为止,我记得正确的语法是:
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
百分号是检查环境变量的暗示。
这是作为原始提问者的编辑添加的,我已将其转换为社区维基答案,因为它应该是答案,而不是编辑。
我发现了怎么做......无论如何都是这样。
http://www.robvanderwoude.com/errorlevel.php
IF ERRORLEVEL 0 [cmd]每次都会执行,因为IF ERRORLEVEL#检查ERRORLEVEL的值是否大于或等于#。因此,每个错误代码都会导致执行[cmd]。
一个很好的参考是:>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
我建议您将代码修改为以下内容:
: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
如果你需要处理多个ERRORLEVEL的东西,你可以这样做:
: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
要么
%~1
aschipfl的答案很棒(谢谢,帮了我很多!)使用Presetting ErrorLevel下的代码你会得到一个很好的标准函数:
注意在%1
语句中使用del
而不是::######################################################################
::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
,否则如果使用带引号的文件名,则会出错。
::
顺便说一句:你可以给出一个漂亮的错误信息作为第二个参数
顺便说一句2:使用REM
而不是qazxswpoi进行注释使代码更具可读性。