Let’s make our bash scripts intelligent!
In this part of the bash beginner series, you will learn how to use conditional statements in your bash scripts to make it behave differently in different scenarios and cases.
This way you can build much more efficient bash scripts and you can also implement error checking in your scripts.
Using if statement in bash
The most fundamental construct in any decision-making structure is an if condition. The general syntax of a basic if statement is as follows:
if [ condition ]; then your code fi
if statement is closed with a
fi (reverse of if).
Pay attention to white space!
- There must be a space between the opening and closing brackets and the condition you write. Otherwise, the shell will complain of error.
- There must be space before and after the conditional operator (=, ==, <= etc). Otherwise, you'll see an error like "unary operator expected".
Now, let's create an example script root.sh. This script will echo the statement “you are root” only if you run the script as the root user:
#!/bin/bash if [ $(whoami) = 'root' ]; then echo "You are root" fi
whoami command outputs the username. From the bash variables tutorial, you know that
$(command) syntax is used for command substitution and it gives you the output of the command.
$(whoami) = 'root' will be true only if you are logged in as the root user.
Don't believe me? You don't have to. Run it and see it for yourself.
Using if-else statement in bash
You may have noticed that you don’t get any output when you run the root.sh script as a regular user. Any code you want to run when an if condition is evaluated to false can be included in an else statement as follows:
#!/bin/bash if [ $(whoami) = 'root' ]; then echo "You are root" else echo "You are not root" fi
Now when you run the script as a regular user, you will be reminded that you are not the almighty root user:
[email protected]:~$ ./root.sh You are not root
Using else if statement in bash
You can use an elif (else-if) statement whenever you want to test more than one expression (condition) at the same time.
For example, the following age.sh bash script takes your age as an argument and will output a meaningful message that corresponds to your age:
#!/bin/bash AGE=$1 if [ $AGE -lt 13 ]; then echo "You are a kid." elif [ $AGE -lt 20 ]; then echo "You are a teenager." elif [ $AGE -lt 65 ]; then echo "You are an adult." else echo "You are an elder." fi
By now you know how to pass arguments to bash scripts. Let's do a few runs of the age.sh script to test out with different ages:
[email protected]:~$ ./age.sh 11 You are a kid. [email protected]:~$ ./age.sh 18 You are a teenager. [email protected]:~$ ./age.sh 44 You are an adult. [email protected]:~$ ./age.sh 70 You are an elder.
Notice that I have used the
-lt (less than) test condition with the $AGE variable.
Also be aware that you can have multiple
elif statements but only one
else statement in an if construct and it must be closed with a
Using nested if statements in bash
You can also use an if statement within another if statement. For example, take a look at the following weather.sh bash script:
#!/bin/bash TEMP=$1 if [ $TEMP -gt 5 ]; then if [ $TEMP -lt 15 ]; then echo "The weather is cold." elif [ $TEMP -lt 25 ]; then echo "The weather is nice." else echo "The weather is hot." fi else echo "It's freezing outside ..." fi
The script takes any temperature as an argument and then displays a message that reflects what would the weather be like. If the temperature is greater than five, then the nested (inner) if-elif statement is evaluated. Let’s do a few runs of the script to see how it works:
[email protected]:~$ ./weather.sh 0 It's freezing outside ... [email protected]:~$ ./weather.sh 8 The weather is cold. [email protected]:~$ ./weather.sh 16 The weather is nice. [email protected]:~$ ./weather.sh 30 The weather is hot.
Using Case statement in bash
You can also use case statements in bash to replace multiple if statements as they are sometimes confusing and hard to read. The general syntax of a case construct is as follows:
case "variable" in "pattern1" ) Command … ;; "pattern2" ) Command … ;; "pattern2" ) Command … ;; esac
- The patterns are always followed by a blank space and
- Commands are always followed by double semicolon
;;. White space is not mandatory before it.
- Case statements end with
esac(reverse of case).
Case statements are particularly useful when dealing with pattern matching or regular expressions. To demonstrate, take a look at the following char.sh bash script:
#!/bin/bash CHAR=$1 case $CHAR in [a-z]) echo "Small Alphabet." ;; [A-Z]) echo "Big Alphabet." ;; [0-9]) echo "Number." ;; *) echo "Special Character." esac
The script takes one character as an argument and displays whether the character is small/big alphabet, number, or a special character.
[email protected]:~$ ./char.sh a Small Alphabet. kab[email protected]:~$ ./char.sh Z Big Alphabet. [email protected]:~$ ./char.sh 7 Number. [email protected]:~$ ./char.sh $ Special Character.
Notice that I have used the wildcard asterisk symbol (*) to define the default case which is the equivalent of an else statement in an if condition.
Test conditions in bash
There are numerous test conditions that you can use with if statements. Test conditions varies if you are working with numbers, strings, or files. Think of them as logical operators in bash.
I have included some of the most popular test conditions in the table below:
|$a -lt $b||$a < $b|
|$a -gt $b||$a > $b|
|$a -le $b||$a <= $b|
|$a -ge $b||$a >= $b|
|$a -eq $b||$a is equal to $b|
|$a -ne $b||$a is not equal to $b|
|-e $FILE||$FILE exists|
|-d $FILE||$FILE exists and is a directory.|
|-f $FILE||$FILE exists and is a regular file.|
|-L $FILE||$FILE exists and is a soft link.|
|$STRING1 = $STRING2||$STRING1 is equal to $STRING2|
|$STRING1 != $STRING2||$STRING1 is not equal to $STRING2|
|-z $STRING1||$STRING1 is empty|
Luckily, you don’t need to memorize any of the test conditions because you can look them up in the test man page:
[email protected]:~$ man test
Let’s create one final script named filetype.sh that detects whether a file is a regular file, directory or a soft link:
#!/bin/bash if [ $# -ne 1 ]; then echo "Error: Invalid number of arguments" exit 1 fi file=$1 if [ -f $file ]; then echo "$file is a regular file." elif [ -L $file ]; then echo "$file is a soft link." elif [ -d $file ]; then echo "$file is a directory." else echo "$file does not exist" fi
I improved the script a little by adding a check on number of arguments. If there are no arguments or more than one argument, the script will output a message and exit without running rest of the statements in the script.
Let’s do a few runs of the script to test it with various types of files:
[email protected]:~$ ./filetype.sh weather.sh weather.sh is a regular file. [email protected]:~$ ./filetype.sh /bin /bin is a soft link. [email protected]:~$ ./filetype.sh /var /var is a directory. [email protected]:~$ ./filetype.sh Error: Invalid number of arguments
Bonus: Bash if else statement in one line
So far all the if else statement you saw were used in a proper bash script. That's the decent way of doing it but you are not obliged to it.
When you just want to see the result in the shell itself, you may use the if else statements in a single line in bash.
Suppose you have this bash script.
if [ $(whoami) = 'root' ]; then echo "You are root" else echo "You are not root" fi
You can use all the if else statements in a single line like this:
if [ $(whoami) = 'root' ]; then echo "root"; else echo "not root"; fi
You can copy and paste the above in terminal and see the result for yourself.
Basically, you just add semicolons after the commands and then add the next if-else statement.
Awesome! This should give you a good understanding of conditional statements in Bash. I hope you have enjoyed making your bash scripts smarter!
You can test your newly learned knowledge by practicing some simple bash exercises in the PDF below. It includes the solution as well.
Stay tuned for next week as you will learn to use various loop constructs in your bash scripts.