CALL — вызов bat-файлов и подпрограмм из командного файла CMD

Команда CALL запускает другой bat-файл или вызывает метку-подпрограмму внутри текущего скрипта, возвращая управление после завершения. Основа структурирования сложных bat-скриптов.

CALL — вызов bat-файлов и подпрограмм из командного файла CMD

Команда CALL запускает другой командный файл (.bat или .cmd) или переходит к именованной метке внутри текущего скрипта, возвращая управление вызывающему скрипту после завершения вызванного блока. Без CALL запуск внешнего bat-файла завершает выполнение текущего скрипта — управление не возвращается. CALL является основой модульного программирования в CMD: позволяет организовывать подпрограммы, переиспользовать код и передавать параметры.

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

CALL [диск:][путь]имя_файла [параметры]
CALL :метка [параметры]
CALL команда [параметры]

Плейсхолдеры:

  • [диск:][путь]имя_файла — путь к вызываемому .bat или .cmd файлу.
  • :метка — имя метки внутри текущего файла (начинается с двоеточия). Это вызов подпрограммы.
  • параметры — аргументы, передаваемые в вызванный файл или подпрограмму; доступны через %1, %2, … %9.
  • Третья форма CALL команда запускает встроенную команду CMD или внешнюю программу с возвратом управления.

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

Элемент Описание Пример
%1%9 Позиционные параметры, переданные при вызове. %1 — первый аргумент, %9 — девятый CALL :func значение1 значение2
%~1 Убирает кавычки из значения параметра %1 SET param=%~1
%~f1 Расширяет %1 до полного пути к файлу ECHO %~f1
%~dp0 Путь к каталогу, в котором находится текущий скрипт (часто используется для относительных путей) CALL "%~dp0\helper.bat"
GOTO :EOF Завершает выполнение подпрограммы и возвращает управление вызывающей строке (специальная метка :EOF) В конце каждой подпрограммы
ERRORLEVEL После возврата из CALL содержит код завершения вызванного файла или подпрограммы IF ERRORLEVEL 1 ECHO Error

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

Вызов внешнего bat-файла с возвратом управления

Без CALL запуск другого bat-файла прерывает текущий скрипт. CALL гарантирует возврат управления.

CALL C:\Scripts\setup.bat
ECHO Setup completed, continuing...

После завершения setup.bat выполнение продолжится со следующей строки — вывода сообщения.

Вызов с передачей параметров

Аргументы передаются через пробел после имени файла и доступны в вызванном скрипте как %1, %2 и т.д.

CALL C:\Scripts\deploy.bat production 8080 "C:\App"

Внутри deploy.bat: %1 = production, %2 = 8080, %3 = C:\App.

Вызов подпрограммы внутри текущего файла

Метка с двоеточием определяет начало подпрограммы. GOTO :EOF возвращает управление обратно.

CALL :CheckFreeSpace C: 5000
ECHO Done.
GOTO :EOF

:CheckFreeSpace
SET drive=%1
SET required=%2
ECHO Checking %drive% for %required% MB free...
GOTO :EOF

Конструкция GOTO :EOF в конце подпрограммы — стандартный паттерн завершения. Без неё выполнение «провалится» в следующую метку.

Использование %~dp0 для надёжных относительных путей

Скрипты с жёсткими путями ломаются при переносе. %~dp0 всегда содержит каталог текущего скрипта.

CALL "%~dp0\lib\functions.bat"
CALL "%~dp0\lib\logging.bat"

Скрипт будет работать из любого каталога, потому что пути строятся относительно его местоположения.

Проверка результата вызова через ERRORLEVEL

После возврата из CALL можно проверить код завершения и принять решение о дальнейших действиях.

CALL C:\Scripts\backup.bat
IF ERRORLEVEL 1 (
    ECHO Backup failed with error %ERRORLEVEL%
    EXIT /B 1
)
ECHO Backup successful.

Ненулевой ERRORLEVEL сигнализирует об ошибке — скрипт завершится с тем же кодом.

Рекурсивный вызов подпрограммы (цикл через CALL)

CALL позволяет организовать итеративную обработку списка элементов.

FOR %%F IN (*.log) DO CALL :ProcessLog "%%F"
GOTO :EOF

:ProcessLog
ECHO Processing: %~1
COPY "%~1" "C:\Archive\" /Y
GOTO :EOF

Каждый .log файл обрабатывается подпрограммой :ProcessLog, которая копирует его в архив.

Вызов команды CMD с возвратом управления

CALL можно использовать для вызова встроенных команд, когда нужен явный возврат управления.

CALL SET result=%%VAR:old=new%%

Трюк с CALL SET используется для двойного раскрытия переменных в одном проходе парсера CMD.

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

Ошибка / поведение Причина Решение
После вызова внешнего bat управление не возвращается Внешний скрипт запущен без CALL (просто по имени файла или через START) Использовать CALL имя.bat вместо просто имя.bat
Подпрограмма выполняется дважды или «проваливается» в следующую Отсутствует GOTO :EOF в конце основного кода или в конце подпрограммы Добавить GOTO :EOF после основного кода (до первой метки) и в конце каждой подпрограммы
Параметр с пробелами обрезается Аргумент передан без кавычек: CALL :func C:\My Folder Заключить аргумент в кавычки: CALL :func "C:\My Folder"; внутри подпрограммы использовать %~1
Переменные, изменённые в подпрограмме, недоступны снаружи Используется SETLOCAL внутри подпрограммы без ENDLOCAL Вернуть значение через глобальную переменную до ENDLOCAL: ENDLOCAL & SET result=%result%
CALL :метка не работает — метка не найдена Метка находится во внешнем файле, а не в текущем; или опечатка в имени метки Убедиться, что метка определена в том же файле. Для внешнего файла — CALL файл.bat :метка (не все CMD поддерживают)

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

Используйте CALL всякий раз, когда bat-скрипт запускает другой bat-файл и должен продолжить работу после его завершения. Без CALL вызов другого bat прерывает родительский скрипт — это классическая ошибка. CALL :метка незаменима для организации подпрограмм и устранения дублирования кода. Ограничение: передать можно не более 9 позиционных параметров напрямую (обходится через SET или shift). Для сложной автоматизации, где нужны объекты, параллельное выполнение или обработка исключений, переходите на PowerShell с его функциями, параметрами и конструкцией try/catch — это значительно мощнее bat-подпрограмм.

FAQ

Зачем CALL, если можно просто написать имя bat-файла?

Если написать имя bat-файла без CALL, интерпретатор CMD передаёт управление новому скрипту и не возвращается в старый. CALL создаёт «стек вызовов»: после завершения вызванного скрипта CMD возвращается к следующей строке вызывающего.

Можно ли передать более 9 параметров через CALL?

Напрямую — нет. Обходные пути: использовать переменные среды для передачи дополнительных данных, или команду SHIFT для сдвига параметров внутри подпрограммы.

Чем CALL :метка отличается от GOTO :метка?

GOTO безвозвратно перемещает выполнение к метке — возврата нет. CALL :метка создаёт подпрограмму с возвратом: после GOTO :EOF в подпрограмме управление вернётся к строке, следующей за CALL.

Как из подпрограммы вернуть значение в основной скрипт?

Через переменную среды: установите её в подпрограмме (SET result=значение) и читайте после возврата. Если используется SETLOCAL, применяйте трюк: ENDLOCAL & SET result=%result% — это передаёт переменную в внешний контекст.

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

CALL — это встроенная команда CMD и не является командлетом PowerShell. В PowerShell для вызова внешних скриптов используйте & "script.ps1" или . "script.ps1" (dot-sourcing для импорта функций в текущий контекст).

Как вызвать bat-файл, путь к которому содержит пробелы?

Заключить путь в кавычки: CALL "C:\My Scripts\setup.bat". Без кавычек CMD разобьёт путь по пробелам и не найдёт файл.

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

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