Сохранить значения командного файла - PullRequest
0 голосов
/ 01 февраля 2012

Я написал этот скрипт для поиска тома с достаточным количеством свободного места:

@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 не сохраняет свое значение. выход (эхо включено)

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

похоже, что bytesfree потерял свою ценность. Может кто-нибудь, пожалуйста, помогите? и дать некоторые объяснения? спасибо.

Ответы [ 2 ]

4 голосов
/ 01 февраля 2012

Чтобы развернуть ответ Джоуи (оригинальный короткий), все выражения for анализируются сразу, а расширение% происходит во время разбора.Но нужного вам значения не существует, пока не выполнится предложение DO.Вот почему вам нужно отсроченное расширение.Прочтите справку для, набрав HELP FOR в командной строке.

На основании комментария к предыдущему вопросу https://stackoverflow.com/a/9096601/1012053, похоже, что вы пытаетесь найти диск с наибольшим количеством свободного места>1 ГБ.

Ваш текущий код имеет небольшой риск включения неправильной строки из команды DIR.Я изменил его, чтобы отфильтровать вывод с использованием FINDSTR с регулярным выражением.

EDIT - Кроме того, команда 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
2 голосов
/ 01 февраля 2012

Краткий ответ:

Используйте

setlocal enabledelayedexpansion

вместо просто setlocal и затем используйте !bytesfree! для ссылки на переменную (просто замените % на !).


Более длинный ответ:

Это связано с тем, что cmd расширяет переменные, поскольку анализирует команду, а не во время ее выполнения (что, очевидно, происходит после анализа). Команда в этом случае также может быть полным for оператором , включая блок после него. Таким образом, все экземпляры %bytesfree% в цикле заменяются на их значение до цикла, которое оказывается пустой строкой.

Отсроченное расширение - это особая форма расширения переменных, которая расширяет переменные при выполнении команды, а не при ее разборе. Может быть включен с

setlocal enabledelayedexpansion

(внутри пакетного файла) или

cmd /v:on

(для полного сеанса, но , а не в пакетном файле, если вы не хотите, чтобы он возобновлялся).

Затем синтаксис !bytesfree! используется для ссылки на переменные, которые затем раскрываются непосредственно перед выполнением команды. Таким образом, при установке и с использованием одной и той же переменной в пределах блока (for loop, if и т. Д.) Вы почти всегда хотите использовать отложенное расширение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...