保存值批处理文件

时间:2012-02-01 16:08:54

标签: batch-file cmd

我编写了这个脚本来寻找具有足够可用空间的卷:

@echo on
setlocal
set gbsize=1,073,741,824
Set gbsize=%gbsize:,=%

for %%A in (A B C D) do ( 
for /f "tokens=3,4,5,*" %%B in ('dir %%A:\') do (
set bytesfree=%%B
set bytesfree=%bytesfree:,=%
if %%D == free If %bytesfree% gtr %gbsize% echo hi
)
)

我的问题是bytesfree变量dosent保存其值。输出是(回声打开)

C:\Users\Desktop>(
set bytesfree=**780,607,488**
 set bytesfree=**23167987712**
 if free == free If 23167987712 GTR 1073741824 echo hi
)
hi

看起来像bytesfree失去了它的值。 有人可以帮忙吗?并提供一些解释? 感谢。

2 个答案:

答案 0 :(得分:4)

要扩展Joey(原始简短)的答案,将立即解析整个for表达式,并在解析时发生%扩展。但是在DO子句执行之前,你想要的值就不存在了。这就是你需要延迟扩张的原因。通过从命令行键入HELP FOR来阅读有关的帮助。

根据您之前提问https://stackoverflow.com/a/9096601/1012053的评论,您似乎正在尝试查找具有最多可用空间的驱动器> 1GB。

您当前的代码存在从DIR命令中包含错误行的轻微风险。我已修改它以使用带有正则表达式的FINDSTR过滤输出。

编辑 - 此外,IF命令无法正确比较超过2147483647的数字。

>if 2147483647 gtr 2147483646 echo greater
greater

>if 2147483648 gtr 2147483647 echo greater

>if 1000000000000 gtr 2147483647 echo greater

>if 2147483648 equ 2147483647 echo equal
equal

>if 1000000000000 equ 2147483647 echo equal
equal

因此数字必须为0前缀,并且必须强制IF命令进行字符串比较而不是数字比较。我通过在引号中包含0前缀数字来强制进行字符串比较。

@echo off
setlocal enableDelayedExpansion
set "gbsize=1,073,741,824"
set "gbsize=%gbsize:,=%"
set "maxfree=000000000000000"
set "maxdrive="
for %%A in (C D) do (
  for /f "tokens=3" %%B in ('dir %%A:\^|findstr /r /c:"^ *.* *Dir(s).*bytes free$"') do (
    set "bytesfree=000000000000000%%B"
    set "bytesfree=!bytesfree:,=!"
    set "bytesfree=!bytesfree:~-15!"
    if "!bytesfree!" gtr "!maxfree!" (
      set "maxfree=!bytesfree!"
      set "maxdrive=%%A:"
    )
  )
)
for /f "tokens=* delims=0" %%A in ("%maxfree%") do set maxfree=%%A
echo Drive with max free space is %maxdrive%  %maxfree% bytes free
if %maxfree% gtr %gbsize% echo That is more than 1GB

使用WMIC的替代方法

@echo off
setlocal enableDelayedExpansion
set "gbsize=1,073,741,824"
set "gbsize=%gbsize:,=%"
set "maxfree=000000000000000"
set "maxdrive="
for /f "skip=1 tokens=1,2" %%A in ('wmic volume get DriveLetter^, FreeSpace') do (
  if "%%B" neq "" (
    set "bytesfree=000000000000000%%B"
    set "bytesfree=!bytesfree:~-15!"
    if "!bytesfree!" gtr "!maxfree!" (
      set "maxfree=!bytesfree!"
      set "maxdrive=%%A"
    )
  )
)
for /f "tokens=* delims=0" %%A in ("%maxfree%") do set maxfree=%%A
echo Drive with max free space is %maxdrive%  %maxfree% bytes free
if %maxfree% gtr %gbsize% echo That is more than 1GB

答案 1 :(得分:2)

简答:

使用

setlocal enabledelayedexpansion

而不只是setlocal,然后使用!bytesfree!来引用变量(只需将%替换为!)。


更长的回答:

这是因为cmd扩展变量,因为它解析一个命令,而不是在运行命令时(显然在解析之后发生)。在这种情况下,命令也可以是完整的for语句,包括之后的块。因此,循环中<{1}} 的所有实例都会在循环之前被它们的值替换,这恰好是一个空字符串。

延迟扩展是一种特殊形式的变量扩展,它在运行命令时扩展变量,而不是在解析时扩展变量。可以使用

启用它
%bytesfree%

(在批处理文件中)或

setlocal enabledelayedexpansion

(对于完整的会话,但在批处理文件中,除非您不希望它恢复)。

然后语法cmd /v:on 用于引用在运行命令之前扩展的变量。因此,当在块(!bytesfree!循环,for等)中使用相同的变量设置时,您几乎总是希望使用延迟扩展