You can control the execution of Linux commands in a shell script with control structures. Control structures allow you to repeat commands and to select certain commands over others. A control structure consists of two major components: a test and commands. If the test is successful, then the commands are executed. In this way, you can use control structures to make decisions as to whether commands should be executed.
There are two different kinds of control structures: loops and conditions. A loop repeats commands, whereas a condition executes a command when certain conditions are met. The BASH shell has three loop control structures:
while ,
for , and
for-in . There are two condition structures:
if and
case . The control structures have as their test the execution of a Linux command. All Linux commands return an exit status after they have finished executing. If a command is successful, its exit status will be 0. If the command fails for any reason, its exit status will be a positive value referencing the type of failure that occurred. The control structures check to see if the exit status of a Linux command is 0 or some other value. In the case of the
if and
while structures, if the exit status is a zero value, then the command was successful and the structure continues.
With the
test command, you can compare integers, compare strings, and even perform logical operations. The command consists of the keyword
test followed by the values being compared, separated by an option that specifies what kind of comparison is taking place. The option can be thought of as the operator, but it is written, like other options, with a minus sign and letter codes. For example,
-eq is the option that represents the equality comparison. However, there are two string operations that actually use an operator instead of an option. When you compare two strings for equality you use the equal sign,
= . For inequality you use
!= . Table 8-6 lists some of the commonly used options and operators used by
test . The syntax for the
test command is shown here:
test value -option value test string = string
Integer Comparisons |
Function |
---|---|
-gt |
Greater-than |
-lt |
Less-than |
-ge |
Greater-than-or-equal-to |
-le |
Less-than-or-equal-to |
-eq |
Equal |
-ne |
Not-equal |
String Comparisons | |
-z |
Tests for empty string |
= |
Equal strings |
!= |
Not-equal strings |
Logical Operations | |
-a |
Logical AND |
-o |
Logical OR |
! |
Logical NOT |
File Tests | |
-f |
File exists and is a regular file |
-s |
File is not empty |
-r |
File is readable |
-w |
File can be written to, modified |
-x |
File is executable |
-d |
Filename is a directory name |
In the next example, the user compares two integer values to see if they are equal. In this case, you need to use the equality option,
-eq . The exit status of the
test command is examined to find out the result of the test operation. The shell special variable
$? holds the exit status of the most recently executed Linux command.
$ num=5 $ test $num -eq 10 $ echo $? 1
Instead of using the keyword
test for the
test command, you can use enclosing brackets. The command
test
$greeting
=
"hi" can be written as
$ [ $greeting = "hi" ]
Similarly, the test command
test
$num
-eq
10 can be written as
$ [ $num -eq 10 ]
The brackets themselves must be surrounded by white space: a space, TAB, or ENTER. Without the spaces, it would be invalid.
The BASH shell has a set of conditional control structures that allow you to choose what Linux commands to execute. Many of these are similar to conditional control structures found in programming languages, but there are some differences. The
if condition tests the success of a Linux command, not an expression. Furthermore, the end of an
if-then command must be indicated with the keyword
fi , and the end of a
case command is indicated with the keyword
esac . The condition control structures are listed in Table 8-7.
The
if structure places a condition on commands. That condition is the exit status of a specific Linux command. If a command is successful, returning an exit status of 0, then the commands within the
if structure are executed. If the exit status is anything other than 0, then the command has failed and the commands within the
if structure are not executed. The
if command begins with the keyword
if and is followed by a Linux command whose exit condition will be evaluated. The keyword
fi ends the command. The elsels script in the next example executes the
ls command to list files with two different possible options, either by size or with all file information. If the user enters an
s , files are listed by size; otherwise, all file information is listed.
Condition Control Structures: if, else, elif, case |
Function |
---|---|
if command then command fi |
if executes an action if its test command is true. |
if command then command else command fi |
if-else executes an action if the exit status of its test command is true; if false, then the else action is executed. |
if command then command elif command then command else command fi |
elif allows you to nest if structures, enabling selection among several alternatives; at the first true if structure, its commands are executed and control leaves the entire elif structure. |
case string in pattern ) command ;; esac |
case matches the string value to any of several patterns; if a pattern is matched, its associated commands are executed. |
command && command |
The logical AND condition returns a true 0 value if both commands return a true 0 value; if one returns a non-zero value, then the AND condition is false and also returns a non-zero value. |
command || command |
The logical OR condition returns a true 0 value if one or the other command returns a true 0 value; if both commands return a non-zero value, then the OR condition is false and also returns a non-zero value. |
! command |
The logical NOT condition inverts the return value of the command. |
Loop Control Structures: while, until, for, for-in, select | |
while command do command done |
while executes an action as long as its test command is true. |
until command do command done |
until executes an action as long as its test command is false. |
for variable in list-values do command done |
for-in is designed for use with lists of values; the variable operand is consecutively assigned the values in the list. |
for variable do command done |
for is designed for reference script arguments; the variable operand is consecutively assigned each argument value. |
select string in item-list do command done |
select creates a menu based on the items in the item-list; then it executes the command; the command is usually a case . |
echo Enter s to list file sizes, echo otherwise all file information is listed. echo -n "Please enter option: " read choice if [ "$choice" = s ] then ls -s else ls -l fi echo Good-bye
A run of the program follows:
$ elsels Enter s to list file sizes, otherwise all file information is listed. Please enter option: s total 2 1 monday 2 today $
The
while loop repeats commands. A
while loop begins with the keyword
while and is followed by a Linux command. The keyword
do follows on the next line. The end of the loop is specified by the keyword
done . The Linux command used in
while structures is often a test command indicated by enclosing brackets.
The
for-in structure is designed to reference a list of values sequentially. It takes two operands—a variable and a list of values. The values in the list are assigned one by one to the variable in the
for-in structure. Like the
while command, the
for-in structure is a loop. Each time through the loop, the next value in the list is assigned to the variable. When the end of the list is reached, the loop stops. Like the
while loop, the body of a
for-in loop begins with the keyword
do and ends with the keyword
done . The cbackup script makes a backup of each file and places it in a directory called sourcebak. Notice the use of the
* special character to generate a list of all filenames with a .c extension.
for backfile in *.c do cp $backfile sourcebak/$backfile echo $backfile done
A run of the program follows:
$ cbackup io.c lib.c main.c $
The
for structure without a specified list of values takes as its list of values the command line arguments. The arguments specified on the command line when the shell file is invoked become a list of values referenced by the
for command. The variable used in the
for command is set automatically to each argument value in sequence. The first time through the loop, the variable is set to the value of the first argument. The second time, it is set to the value of the second argument.