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

问题描述:

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

我发现这两个FOR循环使用%1变量的输出 - 在ECHO %1看到和被叫:servermove的每一行。由于缺少更好的解释,因此不会将%1重置为循环之间的空值。

我回顾了几十个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!也不起作用。

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

%1是提供给该过程的第一个参数 - 无论是从命令行(在主过程)或以下在call :procedurename parameter1程序名称的参数。

你的情况,%1:servermoveSourceServers.txt%1:searchlog条目从%LOGFILE%每一行。

既然你已经审查你的批处理,你发布的内容没有多大意义。例如,:searchlogs例程将采用%LOGFILE%的第一行,并根据第一行是否包含目标字符串\\nt转到successmailcleanlogs。它从那里做了什么,我们不知道。

我们遇到了XY problem - 试图修复解决方案,而不是问题。


第一个问题:不要使用date作为用户变量。这是一个“魔术变量”,其中包含日期,但是它被特定的set声明覆盖。

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

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

我也建议您在del /q /s...行后添加一个额外的行

goto :eof 

。这将导致执行被转移到文件结尾(需要:eof中的冒号)并且可能看起来是多余的,但它确保该例程具有定义的端点 - 如果添加进一步的例程,则没有办法:servermove例程将继续进入您的新代码。

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

你的下一个陈述是一个真正的问题。它会做的是抓取日志文件的第一行(其中包含"%DATE% at %HH%%MN%",并且已按照您在开始时设置的日期解析日期文件,然后在:searchlog中处理此行;此行中没有\\nt,因此设置errorlevel到1,批量进行到:EXIT(我认为这不是一个好的标签,因为它是一个关键字);执行exit并应该终止批处理

这似乎不是它实际上在做什么,而我茫然“M解释为什么。

我建议改变

: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 

:mailtest 
find "\\nt" %LOGFILE%>NUL 
IF NOT ERRORLEVEL 1 GOTO successmail 
:failmail 
echo "\\nt" was found in the log 
pause 
GOTO exit 

,但我不能测试...

+0

对不起;我不打算审查有关的信息。它看起来并不重要。我已经更新它以包含文件的全文。再看一遍,我最好的猜测是第一个'FOR'loop将%1设置为文本列表中的最后一个服务器名称(nt-whtever),第二个循环提取相同的%1,它始终是'> nul' – UserUnknown

+0

我使用了@ foxidrive和你自己的'GOTO:EOF'建议,并将':mailtest'部分的代码改为你的建议变体。这工作很好。现在我更好地理解了'goto:eof'的使用,以及搜索文本的新方法,我可以在其他项目中使用它。非常有用和伟大的新知识 - 谢谢! – UserUnknown

我觉得你不能将第一个for循环的%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

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

您在这里缺少一个GOTO :EOF或相似的goto,因为它会下降至低于一次以上是常规完了。

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