How to Exit a Subroutine in Batch Script
In structured batch scripting, a subroutine is a self-contained block of code that performs a specific task. After this task is complete, the script's execution flow must leave the subroutine and return to the point from which it was called. This "return" action is fundamental to making subroutines work correctly.
This guide will teach you the standard and most important command for exiting a subroutine: GOTO :EOF. You will learn what :EOF means, how it works with the CALL command, and see examples of how to use it to create clean, well-structured, and reusable code blocks.
The Core Command: GOTO :EOF
The standard, most common, and most effective way to exit a subroutine is with the command:
GOTO :EOF
This command tells the command processor to stop executing code inside the current subroutine and immediately return to the line following the CALL command that invoked it. Think of it as the return statement in other programming languages.
What is :EOF? (The End-Of-File Label)
:EOF is a special, predefined label that is built into cmd.exe. It conceptually means End Of File. You do not need to (and should not) define a label named :EOF at the end of your script. The GOTO command has a special understanding of this label.
When used with CALL, GOTO :EOF doesn't actually go to the end of the file. Instead, it instructs the interpreter to "pop" the call stack and return to the location it bookmarked when the CALL was made.
Basic Example: A Simple Return
This script defines a simple subroutine. The GOTO :EOF at the end is what makes it a proper, reusable subroutine.
@ECHO OFF
SETLOCAL
ECHO --- Main Script Logic ---
ECHO Calling the subroutine...
CALL :MyTask
ECHO Returned from the subroutine.
ECHO --- Main script finished. ---
GOTO :EOF
REM =============================================
:MyTask
REM This is a simple subroutine.
ECHO Inside the subroutine now.
ECHO Performing the task...
ECHO Exiting the subroutine...
GOTO :EOF
REM =============================================
In the Output, the flow of execution goes into the subroutine and then comes back out.
--- Main Script Logic ---
Calling the subroutine...
Inside the subroutine now.
Performing the task...
Exiting the subroutine...
Returned from the subroutine.
--- Main script finished. ---
How CALL and GOTO :EOF Create a "Round Trip"
This pair of commands forms the foundation of structured scripting.
CALL :MyTask: The interpreter says, "I need to make a detour. I'll place a bookmark right here, on the next line." It then jumps to the:MyTasklabel.- Code Executes: The
ECHOcommands inside the subroutine run in sequence. GOTO :EOF: The interpreter sees this special command and says, "The detour is over. I need to go back to my bookmark." It then jumps to the line right after the originalCALL.
Exiting a Subroutine with an Exit Code (EXIT /B)
An alternative way to exit a subroutine is with the EXIT /B command. This command is very similar to GOTO :EOF, but with one key difference: it allows you to set a custom exit code (%ERRORLEVEL%) for the subroutine itself.
Syntax: EXIT /B [ExitCode]
/B: This is the crucial switch. It means "exit the current batch script or subroutine." Without/B, theEXITcommand would terminate the entirecmd.exesession.[ExitCode]: An optional integer you can provide.
Example of script:
@ECHO OFF
CALL :CheckStatus
ECHO The subroutine returned an exit code of: %ERRORLEVEL%
CALL :CheckStatus "error"
ECHO The subroutine returned an exit code of: %ERRORLEVEL%
GOTO :EOF
:CheckStatus
IF "%~1"=="error" (
EXIT /B 1
) ELSE (
EXIT /B 0
)
Output:
The subroutine returned an exit code of: 0
The subroutine returned an exit code of: 1
Common Pitfalls and How to Solve Them
Problem: Forgetting GOTO :EOF (Fall-Through)
If you forget GOTO :EOF at the end of your subroutine, the interpreter will not know that the subroutine is over. It will simply continue reading and executing the commands that follow, which could be another subroutine, leading to very strange behavior.
Problem: Using EXIT Instead of EXIT /B
This is a critical and destructive mistake.
EXIT /B: Exits the current script/subroutine. This is what you want.EXIT: Exits the entire command prompt session (cmd.exe). If a user runs your script and it contains a plainEXITcommand, their command prompt window will instantly close, which is very user-unfriendly.
Solution: Unless you have a very specific reason to close the user's terminal, always use EXIT /B when you want to terminate a script or subroutine.
Practical Example: A Validation Subroutine with Multiple Exit Points
This subroutine checks if a file exists. It has two possible exit points: one for success and one for failure, each returning a different exit code.
@ECHO OFF
SETLOCAL
CALL :ValidateFile "C:\Windows\System32\kernel32.dll"
IF %ERRORLEVEL% EQU 0 ECHO Validation Succeeded.
CALL :ValidateFile "non_existent_file.txt"
IF %ERRORLEVEL% NEQ 0 ECHO Validation Failed as expected.
GOTO :EOF
:ValidateFile
REM This subroutine checks if a file exists.
REM Returns ERRORLEVEL 0 on success, 1 on failure.
IF EXIST "%~1" (
ECHO File "%~1" found.
EXIT /B 0
) ELSE (
ECHO File "%~1" not found.
EXIT /B 1
)
Conclusion
Exiting a subroutine correctly is just as important as calling it. The GOTO :EOF and EXIT /B commands provide the necessary control flow to create structured and predictable scripts.
Key takeaways:
- Use
GOTO :EOFas the standard way to return from a subroutine. - Use
EXIT /B [N]when you need to exit a subroutine and set a specific exit code. - Never use a plain
EXITcommand unless you intend to close the entire command prompt window. - Ensure every code path in your subroutine ends with either
GOTO :EOForEXIT /Bto prevent "fall-through" errors.