- CALL — вызов bat-файлов и подпрограмм из командного файла CMD
- Синтаксис команды CALL
- Ключи и параметры
- Примеры использования
- Вызов внешнего bat-файла с возвратом управления
- Вызов с передачей параметров
- Вызов подпрограммы внутри текущего файла
- Использование %~dp0 для надёжных относительных путей
- Проверка результата вызова через ERRORLEVEL
- Рекурсивный вызов подпрограммы (цикл через CALL)
- Вызов команды CMD с возвратом управления
- Частые ошибки и решения
- Когда применять, а когда нет
- FAQ
- Зачем CALL, если можно просто написать имя bat-файла?
- Можно ли передать более 9 параметров через CALL?
- Чем CALL :метка отличается от GOTO :метка?
- Как из подпрограммы вернуть значение в основной скрипт?
- Работает ли CALL в PowerShell?
- Как вызвать 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 разобьёт путь по пробелам и не найдёт файл.


