Переменные пакетного файла инициализируются в цикле for - PullRequest
17 голосов
/ 27 марта 2009

У меня есть пакетный файл, который инициализирует переменные с помощью SET внутри цикла for для набора файлов на диске:

for %%f in (%MYTARGETDIR%\*config.xml) do (
  SET TMPFILE=%%F.tmp

  echo In loop %TMPFILE%
)

echo End loop %TMPFILE%

когда я запускаю это в совершенно новой командной оболочке (без определения TMPFILE), эхо в цикле In пусто, но эхо в конце цикла нет.

Когда я запускаю второй раз, он уже установлен и выводит его значение, игнорируя набор, пока цикл не закроется.

Идеи, почему это так, и каков обходной путь?

Ответы [ 5 ]

21 голосов
/ 27 марта 2009

Для записи исправленный скрипт выглядит так:

setlocal ENABLEDELAYEDEXPANSION

for %%f in (%MYTARGETDIR%\*config.xml) do (

  SET TMPFILE=%%F.tmp

  echo In loop !TMPFILE!
)

echo End loop %TMPFILE%

Спасибо Крису за помощь.

16 голосов
/ 27 марта 2009

Это потому, что переменные окружения подставляются, когда команда read . Для следующей команды:

for %%f in (%mytargetdir%\*config.xml) do (
    set tmpfile=%%f.tmp
    echo In loop %tmpfile%
)

вся команда (от for до закрывающей скобки) читается и подставляется перед выполнением.

Вам нужно использовать отложенное расширение, например, с:

@echo off
    setlocal enableextensions enabledelayedexpansion
    set full=/u01/users/pax
:loop1
    if not "!full:~-1!" == "/" (
        set full2=!full:~-1!!full2!
        set full=!full:~,-1!
        goto :loop1
    )
    echo !full!
    endlocal

Когда вы активируете отложенное расширение, маркеры "%" продолжают работать так же, как и раньше, но вы можете использовать маркеры "!" для отложенного расширения.

9 голосов
/ 27 марта 2009

Это потому, что блок () анализируется только один раз, он заменяет% TMPFILE% до запуска цикла.

6 голосов
/ 29 марта 2009

Вы также можете использовать CALL SET вместо отложенного расширения.

2 голосов
/ 05 июля 2012

Обычно я запускаю CMD.EXE с ключами / e: on и / v: on для включения расширений команд и отложенного расширения переменных. Затем все пакетные сценарии, которые я использую, кодируются для проверки того, что расширение отложенной переменной включено.

Впервые слышу, как SETLOCAL принимает аргументы. Я проверил с помощью SETLOCAL /? и конечно же! Это такая экономия времени и кода для меня.

Однако я заметил, что расширения команд должны быть включены в CMD.EXE, прежде чем SETLOCAL распознает параметр ENABLEDELAYEDEXPANSION. Это с выхода SETLOCAL /?

If Command Extensions are enabled SETLOCAL changes as follows:

SETLOCAL batch command now accepts optional arguments:
        ENABLEEXTENSIONS / DISABLEEXTENSIONS
            enable or disable command processor extensions. These
            arguments takes precedence over the CMD /E:ON or /E:OFF
            switches. See CMD /? for details.
        ENABLEDELAYEDEXPANSION / DISABLEDELAYEDEXPANSION
            enable or disable delayed environment variable
            expansion. These arguments takes precedence over the CMD
            /V:ON or /V:OFF switches. See CMD /? for details.

Спасибо вам обоим за этот ценный ответ.

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