我有以下在 ftp 服务器上运行的批处理脚本。我使用传递 4 个变量的调度程序:SouRCe、EXTension、DESTination 和 ZIP Directory。这是一个简单的脚本,需要前 3 个变量,但如果用户不需要压缩文件,则可以省略最后第 4 个变量。
@ECHO OFF
SET SRC=%1
SET EXT=%2
SET DEST=%3
SET ZIPD=%4
SET DTE=%DATE:~4,2%%DATE:~7,2%%DATE:~10,4%
FOR /F "TOKENS=1-3 DELIMS=: " %%L IN ('TIME /T') DO SET hhmm=%%L%%M%
DIR /B /A:-d %SRC%
IF ERRORLEVEL 1 (
ECHO *** There are no files to process. *** RC=%ERRORLEVEL%
SET ERRORLEVEL=0
GOTO EXIT
)
DEL /Q %SRC%\Thumbs.db
IF DEFINED ZIPD (
WZZIP %ZIPD%\%DTE%%hhmm%.zip %SRC%\*%EXT%
IF ERRORLEVEL 1 (
ECHO *** WZZIP for "%SRC%\*%EXT%" failed. *** RC=%ERRORLEVEL%
ECHO.
GOTO EXIT
)
ECHO.
ECHO successfully zipped %SRC% TO %ZIPD%: %DTE%%hhmm%.zip
ECHO.
)
MOVE /Y %SRC%\*%EXT% %DEST%
IF ERRORLEVEL 1 (
ECHO ** MOVE "%SRC%\*%EXT%" TO "%DEST%" Failed. *** RC=%ERRORLEVEL%
)
:EXIT
EXIT /B %ERRORLEVEL%
我遇到的问题是,如果上午 8:15 时目录中没有任何内容(调度程序运行它),
DIR /B /A:-d %SRC%
失败,错误级别为 1。它进入循环并退出。错误级别的测试既可以作为
IF ERRORLEVEL 1
并作为
IF NOT %ERRORLEVEL% == 0
我遇到的问题是,任何后续失败都不会更新 %ERRORLEVEL% 的用户变量。这就是为什么我必须使用 IF ERRORLEVEL 1 进行其他检查的原因。现在,如果 WZZIP 失败,它会进入命令后的循环,但 ECHO 消息会吐出“RC=0”,即使 ERRORLEVEL 必须大于或等于 1,因此应该将 %ERRORLEVEL% 更新为它应该有的值。我测试了脚本,添加了
ECHO %ERRORLEVEL%
每隔一行查看变化,即使 DIR 测试正确更新了 %ERRORLEVEL%,再次 DEL 删除 thumb.db(99.999% 的时间都会失败),结果还是 %ERRORLEVEL% = 0,而 WZZIP 如果被迫失败,结果也是 RC=0。试过 SETLOCAL、SETLOCAL ENABLEEXTENSIONS 和其他一些东西,甚至尝试删除 WZZIP 部分以外的所有内容,但仍然没有更新 %ERRORLEVEL%。这是一个 FTP 服务器,我们不断运行脚本来传输文件,所以我想知道在我运行脚本时,其他 cmd 流是否会更改环境变量,从而产生冲突?此外,大多数其他脚本不是我编写的,他们很喜欢使用SET ERRORLEVEL=whatevernumber
,我知道这在过去给我带来过冲突。我想知道这是否是罪魁祸首。
答案1
你需要延迟扩张如果您想使用变量,请在同一个命令块中更改该变量。(A命令块(
是括号和内的一系列命令)
。)延迟变量使用!var!
而不是来引用%var%
。
例子:
@ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
cmd /C exit /B 99
echo before ^(command block^) %%errorlevel%%=%errorlevel% ^^!errorlevel^^!=!errorlevel!
(
(call)
echo ^(inside command block^) %%errorlevel%%=%errorlevel% ^^!errorlevel^^!=!errorlevel!
(call )
echo ^(inside command block^) %%errorlevel%%=%errorlevel% ^^!errorlevel^^!=!errorlevel!
)
echo after ^(command block^) %%errorlevel%%=%errorlevel% ^^!errorlevel^^!=!errorlevel!
输出:
==> D:\bat\SU\1113027.bat
before (command block) %errorlevel%=99 !errorlevel!=99
(inside command block) %errorlevel%=99 !errorlevel!=1
(inside command block) %errorlevel%=99 !errorlevel!=0
after (command block) %errorlevel%=0 !errorlevel!=0
和(call)
技巧(call )
窃取自这是 Dbenham 的回答将 ERRORLEVEL 设置为 0问题:
如果你想
errorlevel
强制0
,那么您可以使用这个完全非直观但非常有效的语法:(call )
。call 后面的空格非常重要。如果errorlevel
要将1
, 您可以使用(call)
. 至关重要的是,call 之后不能有任何空格。