Библиотека сайта rus-linux.net
7.2. More advanced if usage
7.2.1. if/then/else constructs
7.2.1.1. Dummy example
This is the construct to use to take one course of action if the if commands test true, and another if it tests false. An example:
|
Like the CONSEQUENT-COMMANDS list following the then statement, the ALTERNATE-CONSEQUENT-COMMANDS list following the else statement can hold any UNIX-style command that returns an exit status.
Another example, extending the one from Section 7.1.2.1:
|
We switch to the root account to demonstrate the effect of the else statement - your root is usually a local account while your own user account might be managed by a central system, such as an LDAP server.
7.2.1.2. Checking command line arguments
Instead of setting a variable and then executing a script, it is frequently more elegant to put the values for the variables on the command line.
We use the positional parameters $1
, $2
, ..., $N
for this purpose. $#
refers to the number of command line arguments. $0
refers to the name of the script.
The following is a simple example:
Here's another example, using two arguments:
|
7.2.1.3. Testing the number of arguments
The following example shows how to change the previous script so that it prints a message if more or less than 2 arguments are given:
|
The first argument is referred to as $1
, the second as $2
and so on. The total number of arguments is stored in $#
.
Check out Section 7.2.5 for a more elegant way to print usage messages.
7.2.1.4. Testing that a file exists
This test is done in a lot of scripts, because there's no use in starting a lot of programs if you know they're not going to work:
#!/bin/bash # This script gives information about a file. FILENAME="$1" echo "Properties for $FILENAME:" if [ -f $FILENAME ]; then echo "Size is $(ls -lh $FILENAME | awk '{ print $5 }')" echo "Type is $(file $FILENAME | cut -d":" -f2 -)" echo "Inode number is $(ls -i $FILENAME | cut -d" " -f1 -)" echo "$(df -h $FILENAME | grep -v Mounted | awk '{ print "On",$1", \ which is mounted as the",$6,"partition."}')" else echo "File does not exist." fi |
Note that the file is referred to using a variable; in this case it is the first argument to the script. Alternatively, when no arguments are given, file locations are usually stored in variables at the beginning of a script, and their content is referred to using these variables. Thus, when you want to change a file name in a script, you only need to do it once.
7.2.2. if/then/elif/else constructs
7.2.2.1. General
This is the full form of the if statement:
if TEST-COMMANDS; then
CONSEQUENT-COMMANDS;
elif MORE-TEST-COMMANDS; then
MORE-CONSEQUENT-COMMANDS;
else ALTERNATE-CONSEQUENT-COMMANDS;
fi
The TEST-COMMANDS list is executed, and if its return status is zero, the CONSEQUENT-COMMANDS list is executed. If TEST-COMMANDS returns a non-zero status, each elif list is executed in turn, and if its exit status is zero, the corresponding MORE-CONSEQUENT-COMMANDS is executed and the command completes. If else is followed by an ALTERNATE-CONSEQUENT-COMMANDS list, and the final command in the final if or elif clause has a non-zero exit status, then ALTERNATE-CONSEQUENT-COMMANDS is executed. The return status is the exit status of the last command executed, or zero if no condition tested true.
7.2.2.2. Example
This is an example that you can put in your crontab for daily execution:
|
7.2.3. Nested if statements
Inside the if statement, you can use another if statement. You may use as many levels of nested ifs as you can logically manage.
This is an example testing leap years:
|
7.2.4. Boolean operations
The above script can be shortened using the Boolean operators "AND" (&&) and "OR" (||).
We use the double brackets for testing an arithmetic expression, see Section 3.4.6. This is equivalent to the let statement. You will get stuck using angular brackets here, if you try something like $[$year % 400], because here, the angular brackets don't represent an actual command by themselves.
Among other editors, gvim is one of those supporting colour schemes according to the file format; such editors are useful for detecting errors in your code.
7.2.5. Using the exit statement and if
We already briefly met the exit statement in Section 7.2.1.3. It terminates execution of the entire script. It is most often used if the input requested from the user is incorrect, if a statement did not run successfully or if some other error occurred.
The exit statement takes an optional argument. This argument is the integer exit status code, which is passed back to the parent and stored in the $?
variable.
A zero argument means that the script ran successfully. Any other value may be used by programmers to pass back different messages to the parent, so that different actions can be taken according to failure or success of the child process. If no argument is given to the exit command, the parent shell uses the current value of the $?
variable.
Below is an example with a slightly adapted penguin.sh
script, which sends its exit status back to the parent, feed.sh
:
|
This script is called upon in the next one, which therefore exports its variables menu
and animal
:
|
As you can see, exit status codes can be chosen freely. Existing commands usually have a series of defined codes; see the programmer's manual for each command for more information.