Save values batch file

前端 未结 2 1246
隐瞒了意图╮
隐瞒了意图╮ 2021-01-16 19:39

I wrote this script to looking for volume with enough free space:

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

for %%A in (A B C D) do          


        
相关标签:
2条回答
  • 2021-01-16 20:13

    To expand on Joey's (original short) answer, the entire for expression is parsed at once, and the % expansion occurs at parse time. But the value you want isn't there until the DO clause has executed. That is why you need delayed expansion. Read the help on for by typing HELP FOR from the command line.

    Based on the comment from your previous question https://stackoverflow.com/a/9096601/1012053, it looks like you are attempting to find the drive with the most free space > 1GB.

    Your current code has a slight risk of including the wrong line from the DIR command. I've modified it to filter the output using FINDSTR with a regular expression.

    EDIT - Also, the IF command cannot properly compare numbers that exceed 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
    

    So the numbers need to be 0 prefixed and the IF command must be forced to do a string comparison instead of a numeric comparison. I forced a string comparison by enclosing the 0 prefixed number in quotes.

    @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
    

    An alternate method using 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
    
    0 讨论(0)
  • 2021-01-16 20:28

    Short answer:

    Use

    setlocal enabledelayedexpansion
    

    instead of just setlocal and then use !bytesfree! to refer to the variable (just replace % by !).


    Longer answer:

    This is because cmd expands variables as it parses a command, not when the command is run (which, obviously happens after parsing). A command in this case could also be a complete for statement including the block after it. So all instances of %bytesfree% within the loop are replaced by their value before the loop, which happens to be an empty string.

    Delayed expansion is a special form of variable expansion which expands variables when a command is run instead of when parsing it. It can be enabled with

    setlocal enabledelayedexpansion
    

    (within a batch file) or

    cmd /v:on
    

    (for a complete session, but not in a batch file, unless you don't want it to resume).

    Then the syntax !bytesfree! is used to refer to variables which are then expanded just prior to running a command. So when setting and using the same variable within a block (for loop, if, etc.) you pretty much always want to use delayed expansion.

    0 讨论(0)
提交回复
热议问题