使用%1的两个循环 - 延迟扩展?

时间:2014-07-24 18:49:55

标签: batch-file for-loop delayedvariableexpansion

我的工作批处理文件扫描一长串远程服务器,将任何内容复制到本地服务器,检查日志文件中是否有关键字,以及是否找到关键字发送电子邮件。我注意到它总是发送电子邮件,即使是空白的日志文件。

我发现两个FOR循环都使用%1变量作为输出 - 如ECHO %1和被调用:servermove的每一行所示。由于缺乏更好的解释,它不会在循环之间将%1重置为null。

我回顾了近十几个SO帖子,并且有点自信使用SETLOCAL ENABLEDELAYEDEXPANSION来解决这个问题。这就是我的理解结束的地方,到目前为止我都没有成功。

以下是相关代码:

SET DATE=%date:~4,2%-%date:~7,2%-%date:~10,4%
SET HH=%time:~0,2%
SET MN=%time:~3,2%
SET TSTAMP=Time Run is %HH%%MN%
SET DATETIME=%DATE% at %HH%%MN%
SET LOGFILE="\\nt980a3\CreditFileImagesTransmission\LogFiles\%DATETIME%-File Move Log.txt"

SET MailDst=
SET MailSrc=
SET MailSrcName=Center to LDSD File Mover
SET OKMailSub=A Branch Has Sent You Some Files

ECHO %DATETIME% > %LOGFILE%
ECHO. >> %LOGFILE%

FOR /F "tokens=1" %%A IN (%~dp0SourceServers.txt) DO CALL :ServerMove %%A

:cleanuplogs
PUSHD "\\nt980a3\CreditFileImagesTransmission\LogFiles" &&(
FORFILES /S /M *.txt /D -45 /C "CMD /C DEL /Q @path"
) & POPD

:mailtest
FOR /F "tokens=*" %%A IN (%LOGFILE%) DO CALL :searchlog "%%A"

:searchlog
ECHO %1 | find "\\nt">NUL
IF NOT ERRORLEVEL 1 GOTO successmail
GOTO exit

:successmail
IF EXIST %temp%\to.txt DEL %temp%\to.txt
FOR %%a IN (%MailDst%) DO ECHO %%a>>%temp%\to.txt
"%~dp0sendmail.exe" /TO=%temp%\to.txt /FROM=%MailSrcName% ^<%MailSrc%^> /REF=%OKMailSub% /MESSAGE=%LOGFILE% /HOST=

:exit
EXIT

:ServerMove
DIR /S /B \\%1\CreditFileImagesTransmission\*.* >> %LOGFILE%
XCOPY /E /C /I /Y "\\%1\CreditFileImagesTransmission\*.*" "\\nt980a3\CreditFileImagesTransmission\%DATE%\%HH%%MN%\"
FOR /D %%P IN ("\\%1\CreditFileImagesTransmission\*.*") DO RMDIR "%%P" /Q /S
DEL /Q /S "\\%1\CreditFileImagesTransmission\*.*"

我尝试在两个实例中更改:mailtest以使用%%B,但这也失败了。将SETLOCAL ENABLEDELAYEDEXPANSION及其对应ENDLOCAL置于一个或另一个循环之前并将%%A更改为!A!也不起作用。

有人会以我的方式指出错误并提供有助于我解决此问题的建议或资源吗?

3 个答案:

答案 0 :(得分:1)

%1是提供给过程的第一个参数 - 来自命令行(在主过程中)或call :procedurename parameter1中过程名称后面的参数。

在您的情况下,%1:servermove是来自SourceServers.txt的条目,%1:searchlog是来自%LOGFILE%的每一行。< / p>

由于您已经审查了批次,因此您发布的内容毫无意义。例如,:searchlogs例程将从%LOGFILE%开始,然后转到successmailcleanlogs,具体取决于第一行是否包含目标字符串\\nt 。从那里做了什么,我们无法分辨。

我们面临XY problem - 尝试修复解决方案,而不是问题。


第一个问题:不要将date用作用户变量。它是一个“神奇的变量”,其中包含日期它被特定的set语句覆盖。

:servermove中的每个条目运行SourceServers.txt,您就是 - 从该服务器上的\CreditFileImagesTransmission\*.*累积目录列表。 - 将这些文件复制到服务器nt980a3,日期/时间戳但不包括source-servername ,因此任何重复的名称都将覆盖早期版本。我建议您在目的地名称中加入%1。 - 删除子目录 - 删除文件。

我建议你只删除目录\\%1\CreditFileImagesTransmission\,然后重新创建它。

我还建议您添加额外的行

goto :eof

del /q /s...行之后。这将导致执行被转移到文件结尾(:eof中的冒号是必需的)并且可能看起来多余,但它确保例程具有已定义的端点 - 如果您添加另一个例程,那么:servermove例程不会继续进入新代码。

在处理完每个服务器后,您将继续执行:cleanuplogs例程,我认为该例程会删除超过45天的日志。

你的下一个陈述是一个真正的问题。它将做的是获取日志文件的第一行(其中包含"%DATE% at %HH%%MN%",其日期已在开始时设置,然后在:searchlog中处理此行;没有{ {1}}在此行中,\\nt设置为1,批处理进入errorlevel(在我的视图中不是好标签,因为它是关键字);执行{{1}并且应该终止批处理。

这看起来并不像它实际做的那样,我无法解释原因。

我建议改变

:EXIT

exit

但我无法测试......

答案 1 :(得分:1)

:mailtest
FOR /F "tokens=*" %%A IN (%LOGFILE%) DO CALL :searchlog "%%A"

您在这里错过了GOTO :EOF或类似的转到,因为一旦上述内容完成,它将会进入下面的例行程序。

:searchlog
ECHO %1 | find "\\nt">NUL
IF NOT ERRORLEVEL 1 GOTO successmail
GOTO exit

答案 2 :(得分:0)

我觉得你不能把第一个%1带给别人。尝试将其转移到另一个变量,如下所示。

:ServerMove

set servername=%1

DIR /S /B \\%servername%\CreditFileImagesTransmission\*.* >> %LOGFILE%
XCOPY /E /C /I /Y "\\%servername%\CreditFileImagesTransmission\*.*"     "\\nt980a3\CreditFileImagesTransmission\%DATE%\%HH%%MN%\"
FOR /D %%P IN ("\\%servername%\CreditFileImagesTransmission\*.*") DO RMDIR "%%P" /Q /S
DEL /Q /S "\\%servername%\CreditFileImagesTransmission\*.*"

干杯,G