Learning Batch: The Goto Command

Adam Listek

Read more posts by this author.

In Windows, using batch files to script common tasks has been around for decades. Even though other scripting languages like PowerShell now exist, batch files are still widely used. If you see the goto batch command in a batch file and have always wondered what it does, you’re in luck.

In this tutorial, you will learn how the goto batch command works in batch files with several examples, and where you may still find a use for this older command today!

Prerequisites

As the goto executable is a part of the cmd.exe suite of batch commands, any version of supported Windows will work.

Understanding a Simple goto Command

In a nutshell, the goto command is a way to control the flow of a batch file. Typically, when you execute a batch file, the script executes from top to bottom following each line. But sometimes, you need the script to start executing at a different place in the script. The goto command is perfect for this.

Let’s say you have a batch script with a couple of simple lines to send text to the screen like below.

@echo off
echo Run this line first
echo Run this line second
echo Run this line third

When you run it, as seen below, it sends the three messages to the screen.

Running a simple batch file
Running a simple batch file

Now, perhaps, you’d like to run the third line before the second line. You could cut and paste but for a real batch file, this might not be possible. Instead, you can redirect the batch file with the goto command. To do that, you’ll use the GOTO command combined with a label.

Below you can see three concepts:

  • The goto labels created by starting with a colon with code underneath called run_first, run_last, and run_second.
  • Three GOTO commands that reference those labels.
  • Comments that start with :: to indicate the code is not executable.
  • An optional goto:eof command that tells the batch script to finish or jump to the end of the file (eof). Notice the colon vs. the space here. If you simply use GOTO eof, without the colon, the batch script looks for the label of :eof somewhere in the file and does not jump to the end and return!

When you run the below script, you’ll see that the batch script runs the code in the order that you have the GOTO commands. The goto command changes the flow of the batch script.

@echo off

:: Start comments. The goto commands reference the labels
GOTO run_first
GOTO run_second
GOTO run_last

:: Optional internal goto command that jumps to the end of the script immediately
GOTO:eof

:: Each label starts with a colon
:run_first
echo Run this line first

:run_last
echo Run this line second

:run_second
echo Run this line third
Running a simple batch file
Running a simple batch file

Best Practices Using Labels

In the previous example, you defined labels with an underscore. There’s nothing wrong with this approach but there are many other ways to create these labels. There are several caveats to keep in mind, as not just any label will work.

What will work in a label:

  • Spaces
  • Periods
  • Hypens

What won’t work in a label:

  • Equal signs (=)
  • Semicolons (;)
  • Ending with anything other than a space, colon or CR/LF (carriage return / line-feed) or simply pressing Enter.

Adding various control characters will cause the batch script to run forever in a loop and require manual termination.

If you define a label and the goto command cannot find it, you will receive an error indicating “The system cannot find the batch label specified“.

If a label isn’t found searching forward from the GOTO statement to the end of the file, cmd.exe will restart the search at the beginning of the file.

:: Spaces are OK in labels
GOTO Label with spaces

:Label with spaces
	Echo This is from a label with spaces

:: Underscores, hyphens, and periods are all ok
GOTO Label_hyphenated-with.a.period

:Label_hyphenated-with.a.period
	Echo This label has an underscore, hyphen, and a period

:: Control characters such as semi-colons (;) or equal signs (=) cannot be used
:: GOTO Label=Equal
:: GOTO Label;Semicolon

:: If you specify a GOTO statement but do not have a corresponding label
:: you will see an error
GOTO Label_nonexisting

In fact, if you use either of the GOTO statements with the equal (=) or semicolons (;),

Demonstrating various label iterations
Demonstrating various label iterations

Using the if Command with the goto Command

Jumping to different points of a batch file is handy but in the previous example, it wasn’t practical. To add more practicality, what if you needed a batch script to run some commands only if a certain condition were true?

The goto command used in conjunction with the if command gives you control over exactly when that jump is made. For example, check out the below example. In this example, the batch file is using the call command to run a program. That program will always return an exit code that’s always represented in the internal ERRORLEVEL variable.

The batch file then checks to see if the ERRORLEVEL variable is not equal to 0. If so, it skips to the end of the script. Otherwise, it runs the echo command to tell you that an error has occurred and then skips to the end of the batch script.

@echo off
:: Executing a call command with a single space after will set the %ERRORLEVEL%
:: environmental variable to 1, but not exiting the overall script.
call 
if %ERRORLEVEL% NEQ 0 GOTO End
echo There was an error and the Error Level was set to a non-zero value
GOTO:eof

:: This will never run if there is an error
:End
echo End of the Script

When you run the above script, you’ll see that call returned a non-zero exit code and existed the echo command to tell you an error occurred.

Non-zero exit code
Non-zero exit code

Calling a Subroutine and Using thegoto Command

Now that you have learned the basics of a goto statement, how about using the goto command with a subroutine? A subroutine is like a block of code or a function that you can call to execute. Similar to the goto command, there is a call command which also uses labels.

Unlike the goto command, the call command will run code after the label and then return execution to after the original call command when terminated.

In the below example, this batch file is running the subroutine called my_subroutine using the call command. Then, inside of that subroutine, the batch script runs the goto:eof command to jump to the end of the script.

@echo off
:: Use the SET command to get user input and assign that input to the %Text% variable
set /p Text="Enter Text: "

:: Call the subroutine with the label :my_subroutine and pass in the %text% variable
call :my_subroutine %Text%
:: Return here after the subroutine, echo some text, and then end the script
Echo End of the script
GOTO:eof

:: Run everything in the subroutine
:my_subroutine
:: Each variable passed in is sequentially assigned a variable number, i.e %Text% = %1
Echo User Text: %1
:: Jumps to end of the file, which automatically exits the subroutine
GOTO:eof
batch file is running the subroutine
batch file is running the subroutine

Special Cases, Bugs, and GOTO Statement Considerations!

As with any command, there are special cases, bugs, and important considerations to keep in mind while using the goto statement in your code.

Command Extensions and the :eof Special Label

You may have noticed that the previous examples used extensive use of the :eof label. cmd.exe has both internal and external commands. Although the goto command is built-in to cmd.exe, the special label :eof is known as a command extension.

Command extensions can actually be disabled, via the following methods:

  • Set the DWORD registry key HKCU\Software\Microsoft\Command Processor\EnableExtensionsCommand to 0.
  • Use the option, cmd.exe /e:off to disable command extensions.
  • Within a batch script, run the command SETLOCAL DisableExtensions

Although the goto command will work in most contexts, the special label :eof will no longer take effect. You can get around this limitation by using a goto label at the very end of the batch script.

SETLOCAL DisableExtensions
Echo This will display
:: The following command will break the script as the :eof label does not exist
:: GOTO:eof
GOTO End
	Echo This will not display

:End
The left-hand script fails due to the :eof label, whereas the right-hand script properly goes to the end.
The left-hand script fails due to the :eof label, whereas the right-hand script properly goes to the end.

When you disable command extensions, other cmd.exe functionality also ceases to work such as the dynamic variables, %TIME%.

Using Command Groups and goto Commands in an if Statement

A command group is a series of commands grouped within a parenthesis. This allows an entire set of commands to be operated as one. If you include a goto statement within the command group and an if statement, the remaining conditionals are ignored, such as the below else statement, and the included code is executed.

:: Like before, a call statement without following spaces sets the %ERRORLEVEL% to 1
call
if %ERRORLEVEL% EQU 1 (
	GOTO :subsection
	:subsection
		ECHO This will show since 1 = 1 for the if statement
) else (
	:: This will show even though it should not
	echo This should not show, but will because GOTO within a command group breaks the if statements
)
Demonstrating how a command group with a GOTO statement breaks an if statement
Demonstrating how a command group with a GOTO statement breaks an if statement

As you might imagine, this could have unintended consequences! If, for example, you included a delete command in the else statement that was not intended to run, this goto statement will break that logic.

Next Steps

Despite there being newer automation languages, such as PowerShell, batch files still find use in many different areas, such as package deployment. Understanding how to structure a script with goto statements and control the script flow becomes invaluable to crafting useful automations!

Subscribe to Stay in Touch

Never miss out on your favorite ATA posts and our latest announcements!

Looks like you're offline!