GOTO — безусловный переход в bat-скриптах CMD

GOTO — команда CMD для безусловного перехода к метке в пакетном файле. Используется для организации циклов, ветвления и выхода из скриптов.

Команда GOTO выполняет безусловный переход к указанной метке внутри пакетного файла (.bat или .cmd). Это основной инструмент управления потоком в скриптах CMD: с её помощью строят циклы, ветвления по условию и досрочный выход из скрипта.

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

GOTO метка
GOTO :EOF

Расшифровка:

  • метка — имя метки, определённой в том же файле строкой :метка. При переходе двоеточие перед именем не указывается.
  • :EOF — специальная встроенная метка конца файла. Позволяет завершить выполнение текущего скрипта или подпрограммы (CALL-блока) без объявления реальной метки. Доступна только при расширенной обработке команд (SETLOCAL ENABLEEXTENSIONS, включена по умолчанию).

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

У команды GOTO нет ключей. Единственный аргумент — имя метки или :EOF. Несколько правил о метках:

Правило Пояснение Пример
Объявление метки Метка объявляется строкой, начинающейся с :. Остаток строки после имени игнорируется — можно добавить комментарий. :start или :start -- начало цикла
Регистр не важен GOTO нечувствителен к регистру: GOTO Start и GOTO start — одно и то же. GOTO Start
Длина имени метки CMD распознаёт только первые 8 символов имени метки. Метки :verylongname1 и :verylongname2 будут считаться одинаковыми. Используйте короткие уникальные имена
Специальная метка :EOF Завершает текущий блок CALL или весь скрипт. Не нужно объявлять вручную. GOTO :EOF
GOTO внутри FOR/IF Переход из скобочного блока (...) команды FOR или IF завершает весь блок. Избегайте GOTO внутри FOR ( ... )

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

Простой переход к метке

Нужно пропустить часть кода и перейти прямо к завершению.

@echo off
echo Начало скрипта
GOTO the_end
echo Эта строка никогда не выполнится
:the_end
echo Конец скрипта

Строка между GOTO the_end и :the_end будет пропущена.

Цикл с помощью GOTO

Вывод чисел от 1 до 5 без команды FOR.

@echo off
set i=1
:loop
echo %i%
set /a i+=1
if %i% leq 5 goto loop
echo Конец программы

Скрипт возвращается к метке :loop до тех пор, пока переменная i не превысит 5.

Ветвление по условию

Скрипт должен вести себя по-разному в зависимости от значения переменной.

@echo off
set /p choice=Введите Y для продолжения:
if /i "%choice%"=="Y" goto continue
echo Отменено пользователем.
goto :EOF
:continue
echo Продолжаем выполнение...

Если пользователь не вводит Y, скрипт выводит сообщение и завершается через GOTO :EOF.

Имитация функций через CALL и GOTO

Нужно вынести повторяющийся код в «подпрограмму» внутри одного bat-файла.

@echo off
call :printline "Первый вызов"
call :printline "Второй вызов"
goto :EOF

:printline
echo ------ %~1 ------
goto :EOF

CALL :printline вызывает блок, начинающийся с метки :printline. GOTO :EOF в конце блока возвращает управление в точку после CALL.

Обработка ошибок через GOTO

При неудачном выполнении команды нужно перейти в раздел обработки ошибки.

@echo off
xcopy C:\Source D:\Backup /E /Y
if errorlevel 1 goto error
echo Копирование завершено успешно.
goto :EOF
:error
echo ОШИБКА: xcopy вернул ненулевой код. Проверьте пути.
exit /b 1

Если xcopy завершается с ошибкой, управление переходит к метке :error.

Меню выбора в интерактивном скрипте

Нужно предложить пользователю выбрать действие из списка.

@echo off
:menu
echo 1 - Резервная копия
echo 2 - Очистка temp
echo 3 - Выход
set /p opt=Ваш выбор:
if "%opt%"=="1" goto backup
if "%opt%"=="2" goto cleanup
if "%opt%"=="3" goto :EOF
echo Неверный выбор.
goto menu
:backup
echo Запуск резервного копирования...
goto menu
:cleanup
echo Очистка временных файлов...
goto menu

Скрипт возвращается к :menu после каждого действия до выбора пункта 3.

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

Ошибка / проблема Причина Решение
GOTO: метка не найдена Метка написана с опечаткой или находится в другом файле Проверить написание метки в объявлении (:метка) и в вызове (GOTO метка). Убедиться, что метка в том же файле.
Скрипт уходит в бесконечный цикл Условие выхода из цикла никогда не выполняется Добавить счётчик итераций или проверить логику условия в IF.
GOTO не работает внутри скобок FOR/IF CMD завершает весь блок (...) при переходе через GOTO Переместить GOTO за пределы блока скобок или использовать CALL :подпрограмма.
Длинные имена меток конфликтуют CMD учитывает только первые 8 символов имени метки Давать меткам уникальные имена в пределах первых 8 символов: :bk_daily и :bk_weekly вместо :backup_daily и :backup_weekly.
Переход в файле с CRLF не находит метку Файл сохранён в Unix-формате (LF), CMD не распознаёт строки с метками Убедиться, что bat-файл сохранён с окончаниями строк CRLF (Windows).

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

GOTO уместен в пакетных файлах для организации простого ветвления, имитации функций через CALL :метка и обработки ошибок. Избегайте избыточного использования GOTO в сложных скриптах — «спагетти»-переходы трудно отлаживать. Для полноценных циклов предпочтительнее команда FOR. В PowerShell аналог не нужен: PowerShell поддерживает функции (function), циклы (while, for, foreach) и структурированную обработку ошибок через try/catchGOTO в PowerShell отсутствует как концепция.

FAQ

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

Нет, GOTO — команда только для cmd.exe и пакетных файлов. PowerShell не поддерживает эту команду. Используйте функции, циклы и конструкции break/continue в PowerShell.

Чем GOTO :EOF отличается от EXIT /B?

Оба завершают текущий пакетный файл или подпрограмму. EXIT /B код дополнительно устанавливает код завершения (ERRORLEVEL), тогда как GOTO :EOF сохраняет текущий ERRORLEVEL без изменений.

Можно ли перейти к метке в другом bat-файле?

Нет, GOTO работает только в пределах одного файла. Для вызова другого bat-файла используйте CALL имя_файла.bat или CALL имя_файла.bat :метка для прямого перехода к метке внутри вызываемого файла.

Можно ли использовать GOTO внутри цикла FOR?

Технически да, но переход из блока скобок FOR (...) do (...) завершит весь блок, что часто приводит к непредсказуемому поведению. Лучше вынести логику с GOTO за пределы блока FOR.

Как организовать вложенные «функции» через GOTO?

Используйте CALL :метка вместо GOTO метка. CALL сохраняет точку возврата, а GOTO :EOF в конце блока возвращает управление. Чистый GOTO не возвращается — это безусловный переход.

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

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