By default, the command interpreter (aka the command processor) reads and executes each line in a script, from top to bottom. When you write scripts, you sometimes need to change the order in which the command interpreter executes the code. In other words, you need to change the flow of the script. You can control a script’s flow with the Goto, Call, and Exit commands. To understand these commands, you first need to be familiar with labels.
A label marks a spot to which you want the command interpreter to jump. After the command interpreter jumps to that spot, it starts executing the code downward again. The label’s syntax is
where Label1 is the label’s name preceded by a colon (:). You can specify any name, except for EOF (more on this exception later). As I mentioned in "Shell Scripting 101, Lesson 5,", you can embed spaces in the label but you can’t include commas, semicolons, or other separators. Technically, the label can be any length. However, the command interpreter reads only the first eight characters, which can cause problems if you use several labels that have similar long names. For example, if you have the labels :MyLabel01 and :MyLabel02, the command interpreter reads both labels as :MyLabel0, which can cause errors in a script.
As the code
Echo Fred was here.
shows, the label needs to be the sole element on the line. In other words, you can’t have commands on the same line as the label. Code such as
:Fred Echo Fred was here.
causes an error. You can have as many labels as you want in a script. You use labels with the Goto and Call commands.
The Goto Command
The Goto command moves a script’s flow to the specified label. This command’s syntax is
where Label1 is the name of the label to which you want the command interpreter to jump. For example, in the code that Listing 1 shows, the Goto command tells the command interpreter to jump to the :Fred label. Because the script’s flow jumps from the first line to the third line, the command interpreter never executes the Echo command in the second line.
In the Goto command’s syntax, you might have noted that the colon is in square brackets. Square brackets denote an optional element, which means preceding the label’s name with a colon is optional (except for EOF, which I’ll discuss shortly) in the Goto command. However, because the colon is mandatory in the actual label, including the colon in any label reference is a good habit to get into.
The Call Command
As you’ve just seen, the Goto command tells the command interpreter to go from the current location (point A) to another location (point B), then perform point B’s tasks. The command interpreter doesn’t return to point A when it’s finished with those tasks. Like the Goto command, the Call command tells the command interpreter to go from point A to point B, then perform the tasks. However, unlike the Goto command, the Call command tells the command interpreter to return to point A when it’s finished with those tasks.
For example, in the code that Listing 2 shows, the Call command tells the command interpreter to jump to the :Fred label and display the message Fred was here. The command interpreter then returns to the point from which it made the jump and displays the message Wilma was here.
Another difference between the Call and Goto commands is that you can use the Call command to execute another .bat or .cmd script from within the current script. If you want to call another script, you use the syntax
Call \[drive:\]\[path\] filename \[arguments\]
where filename is the name of the second script. If the second script isn’t in the same directory as the current script, you need to specify the drive and path along with the filename. In the arguments parameter, you specify any command-line arguments that the second script needs to run.
If you want to execute code that lies within the current script (e.g., Listing 2), you use the Call command with a label. In this case, the syntax is
Call :Label1 \[arguments\]
where Label1 is the name of the label that marks the location of the code to execute. Note that the colon preceding the label name isn’t in parentheses. Unlike the Goto command, the Call command requires you to precede the label’s name with a colon. Because the code that follows a label can be a subroutine, the Call command syntax includes the arguments parameter. You use this parameter to provide any command-line arguments that a subroutine might need to run.
If you use the Call command to jump to and execute a subroutine, the command interpreter assumes that the subroutine ends at the end of the file (i.e., with the last command in the script). If the subroutine ends elsewhere, you can use an :EOF label to specify the subroutine’s end.
The :EOF Label and the Exit Command
The :EOF label is a special built-in label that simulates the End of File (EOF). Because :EOF is a built-in label, you can’t use the name EOF for any of your labels.
When you use the :EOF label with the Goto command, you can’t leave out the colon. The Goto :EOF command tells the command interpreter to jump to the end of the script. Let’s look at this command in action. Suppose that you want to delete the file fred.txt, but you’re not sure whether the file is on the C or D drive. As Listing 3 shows, you can write code that uses the If Exist command to test whether the file fred.txt is on the C or D drive. (If you’re unfamiliar with the If Exist command, see "Shell Scripting 101, Lesson 6.") If the file is on the C drive, the command interpreter jumps to the :Delthemc label, deletes the file, and jumps to the end of the script. If the file is on the D drive, the command interpreter jumps to the :Delthemd label, deletes the file, and jumps to the end of the script.
Listing 4 shows another way in which you can write this code. Instead of using the Goto :EOF command, you can use the Exit command. The Exit command quits that session of the command interpreter. Listing 1 and Listing 2 produce identical results.
1. Use labels to modify Listing 1 in "Shell Scripting 101, Lesson 5". Move the script’s flow to a new label and section of code when the counter reaches values 6 through 10.