处理Windows批处理文件的for循环中的变量

时间:2014-03-27 00:06:36

标签: batch-file for-loop token

我已经在StackOverflow之类的线程上对此进行了大量调查,但是虽然我觉得我接近解决方案,但这个问题令我头疼。

我尝试做的事情:当连接特定的外部硬盘驱动器(通过WMIC上的VolumeSerialNumber区分)时,会找到驱动器号,并通过robocopy完成镜像。通过双击执行脚本。这就是我到目前为止所做的:

FOR /F "skip=1" %%i in ('wmic logicaldisk where VolumeSerialNumber^="XXXXXXXX" get deviceid 2^>nul') DO (
    SET y=%%i
    IF [%y%]==[] GOTO hdmissing
    SET "backuphd=%%i"
    GOTO endfor
)
:endfor

robocopy "C:\Users\Herbert\Documents" "%backuphd%\Backup\Documents" /MIR

ECHO Backup done
ECHO end

:hdmissing
ECHO Couldn't find external drive

:end
PAUSE

这样,永远不会检测到外部HD(%y%始终为空字符串)。但是,如果我在同一个控制台会话中执行两次脚本,一切都按预期工作。但是我想让它在第一次执行时工作。

这是我迄今为止所尝试过的:

  • SET y=dummy放在脚本的开头。总是找到HD,触发备份到C:如果HD实际上没有连接(显然SET y=%%i没有改变y?)
  • %y%更改为!y! - 再次找到HD,

2 个答案:

答案 0 :(得分:2)

delayed expansion问题的第3,576代,受污染环境的影响。

没有明显的setlocal,因此y在第一次运行后仍然在环境中设置 - 因此后来的运行特征与首次运行不同[&1;}现象。

在块语句(a parenthesised series of statements)中,解析整个块并执行然后。块中的任何%var%将在解析块时被该变量的值替换 - 在块执行之前 - 同样的事情适用于{{1 }}

因此,FOR ... DO (block)将在遇到IF (something) else (somethingelse)时使用%variables%的值执行。

解决此问题的两种常见方法是1)使用IF并使用setlocal enabledelayedexpansion代替!var!来访问已更改的%var%或2}值以进行调用一个子程序,用于使用更改的值执行进一步处理。

您的案例中的密钥似乎没有varsetlocal enabledelayeexpansion - 因为!y!就是那个 - 文字字符串!y!,除非调用!y!通过delayedexpansion命令。

(话虽如此,

setlocal

会像

一样工作
IF [%%i]==[] GOTO hdmissing

因为SET "y=%%i" IF not defined y GOTO hdmissing if [not] defined var的运行时值进行操作。 var确保该行上的任何杂散尾随空格不包含在分配的值中 )

答案 1 :(得分:0)

正如Magoo已经指出的那样,!y!无效,因为我忘了启用Delayed Expansion。然而,启用它需要你逃避某些角色,这对我来说似乎很烦人和乏味。可以将命令用双引号括在FOR循环中,就像在this question的两个编辑中所做的那样,但是我在解决它之后发现了不同的东西。

我所做的是移动块

IF [%y%]==[] GOTO hdmissing
SET "backuphd=%%i"
:endfor之后

。这样,它就在for循环之外,%y%会相应地扩展。

请注意,此解决方案的工作原理仅仅是因为我只需要一个项目,并且因为编程流程。

其他有用的方法可以在this question中找到。

但是,如果你想做同样的事情:没有WMIC的更容易(虽然不那么强大)解决方案可能包括

  • 在备份之前,将具有特定名称的文件放在硬盘驱动器上并使用IF EXIST进行检查,希望用户不要删除它,并且HD连接到相同的驱动器号。
  • 将批处理脚本放在驱动器本身上并使用相对路径名(可选:在桌面上放置一个快捷方式,并希望驱动器始终在同一个字母下)