我正在编写一个批处理脚本,它将循环遍历文本文件的每一行(每行包含一个文件名),检查文件是否存在,然后运行该文件并移动它 .
这是我的批处理脚本:
REM Loop through each line of input.txt
FOR /F "tokens=1-3 delims=, " %%i IN (./ready/input.txt) DO (
ECHO.
ECHO.
ECHO.
ECHO Check %%i exists, set error flag if it doesnt
if not exist .\ready\%%i set errorlevel=2
echo return code is %errorlevel%
ECHO Run %%i if it exists
if errorlevel 0 call .\ready\%%i
ECHO Move %%i to archive if no error occured
if errorlevel 0 copy .\ready\%%i .\archive\%mydate%_%mytime%_%%j_%%k_%%i
ECHO Copy line of text to the new output.txt file if an error occured
if %errorlevel% NEQ 0 >>output.txt %%i, %%j, %%k
)
这是输出:
我不明白为什么“如果errorlevel”没有按预期工作...如果文件不存在(如在这个例子中它不存在)它不应该尝试运行该文件,它不应该复制文件,它应该回显2而不是0
Edit 1 :我正在阅读SO Post关于"delayed environment variable expansion"我不确定这个问题是否相关
4 回答
这是一个重写的程序 .
注意:
output.txt
在开始时被删除,否则>>
将附加到任何现有文件 .2>nul
如果删除失败(例如文件不存在),则会抑制错误消息在块语句
(a parenthesised series of statements)
中,解析ENTIRE块并执行 THEN . 在块执行之前,块中的任何_844785都将被该变量的值 AT THE TIME THE BLOCK IS PARSED 替换 .因此,
IF (something) else (somethingelse)
将在遇到IF
时使用%variables%
的值执行 .解决此问题的两种常用方法是1)使用
setlocal enabledelayedexpansion
并使用!var!
代替%var%
来访问var
或2的中间值,以调用子例程以使用更改的值执行进一步处理 .因此请注意
CALL ECHO %%var%%
的使用,它显示var
的更改值 .CALL ECHO %%errorlevel%%
显示,但遗憾的是RESETS错误级别 .如果
var
是 CURRENTLY ,则IF DEFINED var
为真 .ERRORLEVEL
是一个特殊的可变形名称 . 它由系统设置,但如果由用户设置,则用户指定的值将覆盖系统值 .如果
errorlevel
是n OR GREATER THAN n ,则IF ERRORLEVEL n
为TRUE .IF ERRORLEVEL 0
因此总是如此 .语法
SET "var=value"
(其中value可以为空)用于确保行末尾的任何杂散空格不包含在指定的值中 .所需命令仅用于测试目的 . 在确认命令正确后,将
ECHO COPY
更改为COPY
以实际复制文件 .我使用了以下
input.txt
:使用包含的现有文件
seterr*.bat
(最后一行中的
1
确定errorlevel
返回)并收到结果输出:
请注意,COPY仅仅是我之前提到过的 .
和output.txt
ERRORLEVEL
和%ERRORLEVEL%
是两个不同的变量 . 这意味着您的代码echo return code is %errorlevel%
和if %errorlevel% NEQ 0 >>output.txt %%i, %%j, %%k
可能是错误的 .ERRORLEVEL
是内置的,用于获取最后一个命令的结果 . 您可以像以下一样使用它:ERRORLEVEL
无法设置,就像bash不会让你set ?= ...
%ERRORLEVEL%
是一个环境变量 . 如果设置了%ERRORLEVEL%
,则在使用%ERRORLEVEL%
时在脚本中使用它 . 如果%ERRORLEVEL%
未设置 AND 如果启用了命令扩展,则它将回退到ERRORLEVEL
.ERRORLEVEL
不更新%ERRORLEVEL%
.Raymond Chen有一篇很好的博客文章:ERRORLEVEL is not %ERRORLEVEL% . 这个答案中的一些内容是无耻地从中解脱出来的 .
使用类似以下子例程的东西:
然后像这样使用它:
所以,整件事情会像以下一样:
TEST.CMD ...
somethingthatfails.cmd ...
somethingthatpasses.cmd ...
这样做的一个副作用是放置一个名为ret.cmd的文件 . 我通常使用:end子例程进行清理并删除它 .
这被设计为仅在存在时执行%% i项目并且检查错误并移动或记录 . 如果%% i项不存在则它将不执行任何操作 .