Команда ENDLOCAL завершает локальную область окружения, открытую командой SETLOCAL: все изменения переменных, текущего диска и директории, сделанные внутри блока, откатываются к состоянию на момент вызова SETLOCAL. Пара SETLOCAL/ENDLOCAL — стандартный способ изолировать скрипт от среды вызывающего процесса.
- Синтаксис команды ENDLOCAL
- Ключи и параметры
- Примеры использования
- Базовая изоляция переменных
- Передача результата наружу через трюк с одной строкой
- Вложенные блоки SETLOCAL/ENDLOCAL
- Изоляция текущей директории
- Использование ENDLOCAL в конце .bat-файла
- Частые ошибки и решения
- Когда применять, а когда нет
- FAQ
- Что происходит, если ENDLOCAL не вызвать явно?
- Можно ли передать несколько переменных через ENDLOCAL?
- Влияет ли ENDLOCAL на переменные, установленные ДО SETLOCAL?
- Сколько уровней вложенности SETLOCAL/ENDLOCAL поддерживает CMD?
- Работает ли ENDLOCAL в PowerShell?
- Как проверить, есть ли активный SETLOCAL-блок?
Синтаксис команды 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% в одной строке |
Забытый SETLOCAL — ENDLOCAL ничего не делает | 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. Или использовать явную структуру скрипта с парными вызовами.


