在XP上的dos批处理文件中未正确设置变量

时间:2013-05-22 19:45:49

标签: windows if-statement batch-file cmd

我正在尝试编写一个批处理文件,以便在XP上的命令提示符下运行。我试图获取遵循某个命名约定的特定路径中的文件列表。我需要将每个文件实例复制并重命名为静态名称,然后将其放到传输文件夹中。

由于文件可能需要一段时间才能进入传输文件夹,因此我需要在复制下一个文件之前进行检查,这样我就不会覆盖以前的文件。我无法使用SLEEPTIMEOUT,因为我没有安装额外的工具包。我尝试不断循环回START部分,直到发送文件为止。

我注意到,如果我通过%%x循环中设置的for值,如果我多次循环回START部分,它似乎会失去其价值,它什么都没有。所以我试着设置一个变量来保存值。

我似乎遇到了未正确设置或未清除变量的问题。最初它继续引用第一个文件,但现在似乎根本没有设置。 ECHO显示正确的值,但filename变量仍为空。

有谁知道更好的方法吗?提前感谢您的帮助,因为我已经浪费了一整天的时间!

这是批处理文件:

@ECHO "At the start of the loop" 
@for %%x in (C:\OUTBOUND\customer_file*) do (
@ECHO "In the loop" 
@ECHO "loop value =" 
@ECHO %%x
SET filename=%%x
@ECHO "filename ="
@ECHO %filename%
@ECHO ...ARCHIVE OUTBOUND CUSTOMER FILE
archivedatafile --sourcefile="%filename%" --archivefolder="..\archivedata\customer" --retentiondays=0
IF NOT %ERRORLEVEL%==0 GOTO ERROR
PAUSE
:START
IF EXIST l:\OutputFile (
@ping 1.1.1.1 -n 1 -w 30000
GOTO START
) ELSE (
COPY %filename% l:\OutputFile /Y
IF NOT %ERRORLEVEL%==0 GOTO ERROR
PAUSE
)
)
GOTO END
:ERROR
@echo off
@ECHO *************************************************************
@ECHO *                      !!ERROR!!                            *
@ECHO *************************************************************
:END
SET filename=

3 个答案:

答案 0 :(得分:4)

foxidrive提供了一个应该有效的脚本,但没有解释为什么你的代码失败以及他如何修复问题。

你有两个问题:

1)只要在你的循环中执行GOTO,你的FOR循环就会立即中止。放置GOTO目标标签无关紧要--GOTO始终终止循环。 Foxidrive对CALL的使用非常有效 - 一旦CALLed例程返回,循环就会继续。

2)您尝试在代码块中设置变量,然后在同一个块中引用新值。解析语句时会扩展%VAR%,并且在一次传递中将IF和FOR等复杂命令整体解析一次。实际上,括号内的任何代码块都会在一次传递中解析。因此%ERRORLEVEL%%FILENAME%的值将保持不变 - 输入块之前存在的值。

正如Endoro所指出的,解决这个问题的一种方法是使用延迟扩展。必须使用setlocal enableDelayedExpansion启用延迟扩展,然后使用!VAR!展开变量。该值在执行时而不是解析时扩展。有关延迟扩展的详细信息,请在命令提示符下键入HELP SET

但要注意延迟扩展在与FOR循环一起使用时会导致自身问题,因为延迟扩展发生在FOR变量扩展之后:如果值包含%%x!将被破坏。通过SETLOCAL和ENDLOCAL根据需要小心切换延迟扩展ON和OFF,可以解决这个问题。

Foxidrive的代码通过使用CALL避免了整个延迟扩展问题。他的:NEXT例程不在FOR循环中,因此每次调用时都会重新解析所有命令,因此不需要延迟扩展。

答案 1 :(得分:1)

这可能有效 - 未经测试:

@echo off
ECHO Starting...
for %%x in (C:\OUTBOUND\customer_file*) do call :next "%%x"
echo done
pause
goto :eof
:next
ECHO ...ARCHIVING OUTBOUND CUSTOMER FILE "%~1"
archivedatafile --sourcefile="%~1" --archivefolder="..\archivedata\customer" --retentiondays=0
IF ERRORLEVEL 1 GOTO :ERROR
:loop
echo waiting for file...
ping -n 6 localhost >nul
IF EXIST l:\OutputFile GOTO :loop
COPY "%~1" l:\OutputFile /Y
IF ERRORLEVEL 1 GOTO :ERROR
GOTO :EOF
:ERROR
ECHO *************************************************************
ECHO * !!ERROR!! in "%%x"
ECHO *************************************************************
pause
goto :EOF

答案 2 :(得分:0)

试试这个:

@echo off&setlocal
for %%x in (C:\OUTBOUND\customer_file*) do SET "filename=%%x"
ECHO %filename%
ECHO ...ARCHIVE OUTBOUND CUSTOMER FILE
archivedatafile --sourcefile="%filename%" --archivefolder="..\archivedata\customer" --retentiondays=0
IF NOT %ERRORLEVEL%==0 GOTO:ERROR
PAUSE
:START
IF EXIST l:\OutputFile ping 1.1.1.1 -n 1 -w 30000&GOTO:START
COPY "%filename%" l:\OutputFile /Y
IF NOT %ERRORLEVEL%==0 GOTO:ERROR
PAUSE
GOTO:END
:ERROR
echo off
ECHO *************************************************************
ECHO *                      !!ERROR!!                            *
ECHO *************************************************************
:END
SET "filename="

如果您使用代码块(iffor( ))和变量值变量,则必须启用delayed expansion。您可以看到,此代码中不需要代码块。