Переменные пакетного файла, инициализированные в цикле for

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

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

  echo In loop %TMPFILE%
)

echo End loop %TMPFILE%

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

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

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

Ответ 1

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

Ответ 2

Для записи скорректированный script выглядит следующим образом:

setlocal ENABLEDELAYEDEXPANSION

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

  SET TMPFILE=%%F.tmp

  echo In loop !TMPFILE!
)

echo End loop %TMPFILE%

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

Ответ 3

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

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

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

Ответ 4

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

Ответ 5

Обычно я вызываю 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.

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