if-then-else

By now, you'll hopefully have a feeling for how useful if-then logic is. However, you might feel like something is missing still. If that is the case, you would be right! An if-then construct is not complete without the ELSE statement. The if-then-else construct allows us to specify what should happen if the test in the if-clause does not equal true. Semantically, it could be translated as:

IF condition, THEN do-something, ELSE (otherwise) do-something-else

We can illustrate this very easily by taking one of our earlier scripts, if-then-exit.sh, and optimizing both the flow of the script and the code:

reader@ubuntu:~/scripts/chapter_09$ cp if-then-exit.sh if-then-else.sh
reader@ubuntu:~/scripts/chapter_09$ vim if-then-else.sh
reader@ubuntu:~/scripts/chapter_09$ cat if-then-else.sh
#!/bin/bash

#####################################
# Author: Sebastiaan Tammer
# Version: v1.0.0
# Date: 2018-09-30
# Description: Use the if-then-else construct.
# Usage: ./if-then-else.sh
#####################################

FILE=/tmp/random_file.txt

# Check if the file exists.
if [[ ! -f ${FILE} ]]; then
echo "File does not exist, stopping the script!"
exit 1
else
cat ${FILE} # Print the file content.
fi

reader@ubuntu:~/scripts/chapter_09$ bash if-then-else.sh
File does not exist, stopping the script!
reader@ubuntu:~/scripts/chapter_09$ touch /tmp/random_file.txt
reader@ubuntu:~/scripts/chapter_09$ bash -x if-then-else.sh
+ FILE=/tmp/random_file.txt
+ [[ ! -f /tmp/random_file.txt ]]
+ cat /tmp/random_file.txt

Now, this is starting to look like something! We moved our cat command into the if-then-else logic block. Now, it feels (and is!) like a single command: if the file does not exist, print an error message and exit, otherwise, print its contents. It is a little weird that we used the then block for the error situation, though; by convention, that is reserved for the success condition. We can make our script a little more intuitive by swapping the then and else blocks; however, we will also need to invert our test condition. Let's take a look:

reader@ubuntu:~/scripts/chapter_09$ cp if-then-else.sh if-then-else-proper.sh
reader@ubuntu:~/scripts/chapter_09$ vim if-then-else-proper.sh
reader@ubuntu:~/scripts/chapter_09$ cat if-then-else-proper.sh
#!/bin/bash

#####################################
# Author: Sebastiaan Tammer
# Version: v1.0.0
# Date: 2018-09-30
# Description: Use the if-then-else construct, now properly.
# Usage: ./if-then-else-proper.sh file-name
#####################################

file_name=$1

# Check if the file exists.
if [[ -f ${file_name} ]]; then
cat ${file_name} # Print the file content.
else
echo "File does not exist, stopping the script!"
exit 1
fi

reader@ubuntu:~/scripts/chapter_09$ bash -x if-then-else-proper.sh /home/reader/textfile.txt
+ FILE=/home/reader/textfile.txt
+ [[ -f /home/reader/textfile.txt ]]
+ cat /home/reader/textfile.txt
Hi, this is some text.

The changes we made in this script are as follows:

  • We replaced the hard-coded FILE constant with a user input variable file_name
  • We removed the ! which inverts the test
  • We swapped the then and else execution blocks

As it is now, the script first checks if the file exists, and if it does, it prints its contents (success scenario). If the file does not exist, the script prints an error message and exits with an exit code of 1 (failure scenario). In practice, else is often reserved for failure scenarios, and then for the success scenario. However, these are not golden rules and could differ, based on the types of test you have available. If you're ever writing a script and you want to use the else block for the success scenario, go right ahead: as long as you're sure it's the right choice for your situation, there is definitely no shame in it!

You might have noticed that within an if-then-else block, the commands we execute in then or else are always preceded by two whitespaces. In scripting/programming, this is called indenting. It serves only a single function in Bash: to improve readability. By indenting those commands with two spaces, we know they're part of the then-else logic. In that same manner, it is much easier to see where the then ends and the else begins. Note that, in some languages, notably Python, whitespace is part of the programming language syntax and cannot be omitted!

Until this point, we have only used if-then-else logic for error detection, followed by an exit 1. However, in some cases, both then and else can be used to accomplish the goal of the script, instead of one of them being used for error handling. Take a look at the following script:

reader@ubuntu:~/scripts/chapter_09$ vim empty-file.sh 
reader@ubuntu:~/scripts/chapter_09$ cat empty-file.sh
#!/bin/bash

#####################################
# Author: Sebastiaan Tammer
# Version: v1.0.0
# Date: 2018-10-02
# Description: Make sure the file given as an argument is empty.
# Usage: ./empty-file.sh <file-name>
#####################################

# Grab the first argument.
file_name=$1

# If the file exists, overwrite it with the always empty file
# /dev/null; otherwise, touch it.
if [[ -f ${file_name} ]]; then
cp /dev/null ${file_name}
else
touch ${file_name}
fi

# Check if either the cp or touch worked correctly.
if [[ $? -ne 0 ]]; then
echo "Something went wrong, please check ${file_name}!"
exit 1
else
echo "Succes, file ${file_name} is now empty."
fi

reader@ubuntu:~/scripts/chapter_09$ bash -x empty-file.sh /tmp/emptyfile
+ file_name=/tmp/emptyfile
+ [[ -f /tmp/emptyfile ]]
+ touch /tmp/emptyfile
+ [[ 0 -ne 0 ]]
+ echo 'Succes, file /tmp/emptyfile is now empty.'
Succes, file /tmp/emptyfile is now empty.
reader@ubuntu:~/scripts/chapter_09$ bash -x empty-file.sh /tmp/emptyfile
+ file_name=/tmp/emptyfile
+ [[ -f /tmp/emptyfile ]]
+ cp /dev/null /tmp/emptyfile
+ [[ 0 -ne 0 ]]
+ echo 'Succes, file /tmp/emptyfile is now empty.'
Succes, file /tmp/emptyfile is now empty.

We use this script to make sure that a file exists and is empty. Basically, there are two scenarios: the file exists (and might not be empty) or it does not exist. In our if test, we check to see if the file exists. If it does, we replace it with an empty file by copying /dev/null (which is always empty) to the location given by the user. Otherwise, if the file does not exist, we simply create it using touch.

As you can see in the script's execution, the first time we run this script, the file does not exist and is created with touch. In the next run of the script, directly after, the file does exist (since it was created in the first run). This time, we can see in the debug that cp is used. Because we want to make sure whether either of these actions succeeded, we include an extra if block, which handles exit status checking, as we have seen before.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.226.104.202