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.
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 calledrun_first
. - 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 useGOTO 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. The first echo
command is never run as the batch script jumps to the specified goto
command. From that point forward, the script executes line-by-line.
@echo off
:: Start comments. The goto commands reference the labels
GOTO run_first
:: Optional internal goto command that jumps to the end of the script immediately
GOTO:eof
echo This line will never be output
:run_first
echo Run this line first
:: Each label starts with a colon
echo Run this line second
echo Run this line third
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 (;),
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.
Calling a Subroutine and Using the goto
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
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
to0
. - 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
When you disable command extensions, other
cmd.exe
functionality also ceases to work such as the dynamic variables,%TIME%
.
Using Command Groups and Goto Batch 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
)
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!