ENDLOCAL — завершение локальной области переменных в CMD-скрипте

ENDLOCAL завершает локальную область, созданную SETLOCAL: все переменные и настройки откатываются к состоянию до SETLOCAL. Обязательна для изолированных скриптов.

Команда ENDLOCAL завершает локальную область окружения, открытую командой SETLOCAL: все изменения переменных, текущего диска и директории, сделанные внутри блока, откатываются к состоянию на момент вызова SETLOCAL. Пара SETLOCAL/ENDLOCAL — стандартный способ изолировать скрипт от среды вызывающего процесса.

Синтаксис команды ENDLOCAL

ENDLOCAL

Команда не принимает параметров. При выполнении:

  • Восстанавливаются все переменные окружения к состоянию перед соответствующим SETLOCAL.
  • Восстанавливается текущий диск и текущая папка.
  • Отключается ENABLEDELAYEDEXPANSION или ENABLEEXTENSIONS, если они были включены через SETLOCAL.

Вложенность: можно использовать несколько пар SETLOCAL/ENDLOCAL, каждый ENDLOCAL закрывает ближайший открытый блок.

Ключи и параметры

Команда ENDLOCAL не имеет собственных ключей. Её поведение определяется тем, как был открыт соответствующий блок через SETLOCAL:

Команда открытия Что откатывает ENDLOCAL
SETLOCAL Переменные, текущий диск и папка
SETLOCAL ENABLEDELAYEDEXPANSION Переменные + отключает отложенное расширение
SETLOCAL ENABLEEXTENSIONS Переменные + отключает расширения команд
SETLOCAL DISABLEEXTENSIONS Переменные + восстанавливает расширения команд

Примеры использования

Базовая изоляция переменных

Защитить переменные вызывающего скрипта от изменений внутри подскрипта — классический сценарий.

SETLOCAL
SET TEMP_VAR=рабочее значение
ECHO %TEMP_VAR%
ENDLOCAL
ECHO %TEMP_VAR%

После ENDLOCAL переменная TEMP_VAR больше не существует — второй ECHO выведет %TEMP_VAR% как литерал или пустую строку.

Передача результата наружу через трюк с одной строкой

Самый популярный сценарий: скрипт вычисляет значение внутри SETLOCAL-блока и должен передать его вызывающему окружению.

SETLOCAL
SET RESULT=вычисленное_значение
ENDLOCAL & SET RESULT=%RESULT%

Трюк работает потому, что CMD вычисляет %RESULT% до того, как выполняет ENDLOCAL, а SET после & уже работает в родительском окружении.

Вложенные блоки SETLOCAL/ENDLOCAL

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

SETLOCAL
SET OUTER=значение_внешнего
  SETLOCAL ENABLEDELAYEDEXPANSION
  SET INNER=значение_внутреннего
  ECHO !INNER!
  ENDLOCAL
ECHO %OUTER%
ENDLOCAL

Первый ENDLOCAL закрывает внутренний блок, второй — внешний. После каждого закрытия соответствующие переменные исчезают.

Изоляция текущей директории

Скрипт меняет рабочую папку, но после завершения возвращает её в исходное состояние.

SETLOCAL
CD /D C:\temp\work
CALL :do_work
ENDLOCAL

После ENDLOCAL рабочая папка вернётся к той, что была при вызове SETLOCAL, независимо от того, сколько раз CD менял её внутри блока.

Использование ENDLOCAL в конце .bat-файла

CMD автоматически вызывает ENDLOCAL при завершении скрипта, но явный вызов делает намерение очевидным и срабатывает в нужной точке.

@ECHO OFF
SETLOCAL
REM ... тело скрипта ...
ENDLOCAL
EXIT /B 0

Явный ENDLOCAL перед EXIT гарантирует, что все локальные переменные сброшены до завершения.

Частые ошибки и решения

Ошибка / симптом Причина Решение
Переменная не передаётся за пределы блока Команда SET стоит после ENDLOCAL в отдельной строке и уже не видит значение Использовать трюк ENDLOCAL & SET VAR=%VAR% в одной строке
Забытый SETLOCALENDLOCAL ничего не делает ENDLOCAL без открытого SETLOCAL просто игнорируется Убедиться, что каждому ENDLOCAL предшествует SETLOCAL
После скрипта в CMD-сессии пропали переменные Скрипт вызван через CALL, но использовал SETLOCAL без ENDLOCAL — автоматический ENDLOCAL при завершении всё откатил Добавить явный ENDLOCAL перед передачей управления обратно
Трюк ENDLOCAL & SET не работает с путями, содержащими & Символ & в пути воспринимается как разделитель команд Заключить значение в кавычки: ENDLOCAL & SET "VAR=%VAR%"
Отложенное расширение (!) не работает после ENDLOCAL ENDLOCAL откатил ENABLEDELAYEDEXPANSION, заданный через SETLOCAL Активировать отложенное расширение заново через новый SETLOCAL ENABLEDELAYEDEXPANSION или через cmd /v:on

Когда применять, а когда нет

ENDLOCAL обязательна во всех нетривиальных bat/cmd-скриптах, которые изменяют переменные окружения — без неё изменения «вытекают» в вызывающую среду и могут сломать другие скрипты. Она работает только внутри сценариев командного интерпретатора Windows; в интерактивной сессии CMD пара SETLOCAL/ENDLOCAL тоже работает, но её смысл теряется при закрытии окна. В PowerShell изоляция переменных встроена по умолчанию: переменные, объявленные внутри функции или блока &{ }, не видны снаружи, поэтому аналог ENDLOCAL не нужен. Если скрипт не использует SETLOCAL, добавлять ENDLOCAL бессмысленно — она просто игнорируется.

FAQ

Что происходит, если ENDLOCAL не вызвать явно?

CMD автоматически вызывает ENDLOCAL при завершении bat-файла, закрывая все открытые блоки SETLOCAL. Однако явный вызов делает код читаемее и позволяет откатить переменные в нужной точке скрипта, а не в самом конце.

Можно ли передать несколько переменных через ENDLOCAL?

Да. Объедините несколько команд SET через & в одной строке: ENDLOCAL & SET "VAR1=%VAR1%" & SET "VAR2=%VAR2%". CMD вычисляет все %VAR% до выполнения ENDLOCAL.

Влияет ли ENDLOCAL на переменные, установленные ДО SETLOCAL?

Нет. ENDLOCAL восстанавливает среду к состоянию на момент вызова SETLOCAL. Переменные, существовавшие до SETLOCAL, вернутся к своим прежним значениям; изменения, сделанные внутри блока, будут отменены.

Сколько уровней вложенности SETLOCAL/ENDLOCAL поддерживает CMD?

CMD поддерживает до 32 уровней вложенности. На практике более 2-3 уровней встречаются редко и усложняют отладку.

Работает ли ENDLOCAL в PowerShell?

Нет. ENDLOCAL — встроенная команда cmd.exe. В PowerShell переменные имеют область видимости по умолчанию, и для изоляции используются функции, модули или блоки скриптов.

Как проверить, есть ли активный SETLOCAL-блок?

Прямого способа проверки нет. Косвенно — изменить тестовую переменную и посмотреть, вернулась ли она после ENDLOCAL. Или использовать явную структуру скрипта с парными вызовами.

Оцените статью
( Пока оценок нет )
MW10
Добавить комментарий

Нажимая на кнопку "Отправить комментарий", я даю согласие на обработку персональных данных и принимаю политику конфиденциальности.