Chapter 12 – Bash Scripting

So far, we have been running commands interactively on the Linux CLI, one command at a time.

Although we have configured some tasks to run at a predetermined schedule using crontab in the previous chapter, they are only tasks that are made up of one single command. We still yet to learn how to run a set of instructions automatically without having to interactively type them on a terminal.

In this chapter, we are finally going to explore how to do that through Bash Scripting.

bash scripting

This is going to be a long chapter, so pour yourself a cup of coffee, sit tight and let’s get to it.

What is Bash Scripting?

Shell

Before we can talk about Bash, we need to first understand what the Shell is.

The Shell is a special program that takes commands from a user and sends them to the operating system for processing before returning the output back to the user. It’s as simple as that. Any program that does this can be called a shell.

So, by this definition, the CLI environment in which we have been executing commands so far is basically a shell program.

Bash

Although people often use Bash and Shell interchangeably, it is very important to distinguish between the two.

There are many types of shells that can be used in Linux, including tcsh, ksh and zsh. However, the most common one is Bash (or Bourne Again SHell). It is the one that we have been working with so far in this tutorial.

Bash Scripting

Bash is also a scripting language. Meaning that, not only can you run Bash commands interactively on the CLI, but you can also create small programs that will execute automated tasks without having to interact with each command individually. These programs are what we call scripts.

Getting Started with Bash Scripting

Creating a script is pretty simple. You just create a new file with the extension of .sh.

However, to specify that you are running a bash shell and not another type of shell, you would need to add the following line at the top of your script file.

#!/bin/bash

This line informs the Linux system that we want to use the bash interpreter, which is located at /bin/bash.

To execute the script, you first have to change your working directory to where the file is located. Then, and this is very important, you would need to add the execute permission to the file using chmod +x. Otherwise, you won’t be able to run the script.

$ chmod +x script.sh

After that, just type the name of the file prefixed by a dot and a slash to run the script.

$ ./script.sh

It is also possible to run a script without having to change the directory to where it’s located. For this, just type the absolute path of the script.

$ /home/spect/script.sh

Now, that we know how to create and run a script file, let’s see how to perform some actual tasks using scripts.

Bash Instructions

A script is simply a set of instructions. The operating system will run the commands from the top of the file down to its bottom.

Thanks to our previous chapters, we already know some Bash commands. Let’s try and combine some of them in a script to execute a task automatically.

I edited the file script.sh from earlier and added the following lines.

#!/bin/bash
cd /home/spect
mv temp/* archive/
echo "Temporary files stored in the archive" >> log.txt

The above script is simple. First, it changes the directory to /home/spect. Then, it moves all files that are located in the directory temp to the archive directory. And finally, it adds an entry at the end of the file log.txt.

The interpreter executes these instructions in series, one after the other. But here, it doesn’t require the user’s interaction to run each command. The only thing a user needs to do is to run the script from the command line.

$ ./script.sh

Comments

A comment is a line of code that does not get interpreted during the execution of the script.

When you run a script, the bash interpreter will simply ignore all comments written in that script.

To write a comment, simply prefix it with a sharp sign #.

# This is a comment

Comments can be useful in documenting your scripts, for yourself as well as for others to read and understand.

Variables

Variables are a crucial element of every programming and scripting language, and Bash isn’t an exception to this.

A variable is an instance that you can create in a script, store a value in it, and then retrieve that value or change it later in the program.

In Bash, you can create a variable using the following basic syntax:

VariableName=value

Notice that there is no space in the variable declaration, Bash is different from other programming languages in this aspect. If we run a script with the line VariableName = value, it would raise an error.

After declaring a variable, You can then use its name to refer to it throughout the program. Whenever the interpreter encounters this variable, it will substitute it with its assigned value.

Here is an example of a simple script that will make this clear:

#!/bin/bash
name="spect"
age=21
echo "Hello! My name is $name, and I am $age year old."

Here is the result when we execute the above script :

$ ./script.sh
Hello! My name is spect, and I am 21 year old.

In this example, we have defined two variables: The first one is the name variable, with a value of “spect”, and the second one is the age variable with a value of 21.

After that, we have printed these variables to the screen using the echo command. When we call variables, we prefix their name with the dollar sign ($). The echo command substitutes the variable names with their corresponding values as the resulted output shows.

Variables can also store the output of commands. Using the expression variable=$(command) will execute “command” and store its output in “variable”.

#!/bin/bash
user=$(whoami)
echo "The script is run by the user : $user"

When we run the above script, we get the following output:

$./script.sh
The script is run by the user : spect

Mathematical operations

When you assign a number to a variable, Bash stores this number as a string. You can test by running the following script.

#!/bin/bash
FirstNumber=1
SecondNumber=2
echo "$FirstNumber+$SecondNumber";

And when we run the script, we get the following result:

$./script.sh
1+2

As you can see, Bash concatenated the 1, + and 2 into 1+2. This is because it treats every variable as a string of characters.

But rest assured, we can still perform arithmetic operations on variables. For this, there are three methods we can use: let, express, or double parenthesis.

As we do not want to end up with a lengthy chapter, we are going to focus here on the double parenthesis option. Here are some examples that will demonstrate how this works:

#!/bin/bash
echo $((1+2))
$./script.sh
3

We can also use the double parenthesis with variables, as demonstrated below.

#!/bin/bash
FirstNumber=1
SecondNumber=2
echo $((FirstNumber+SecondNumber))
$./script.sh
3

Here is another, more interesting example to make this clear.

#!/bin/bash
Number=1
((Number += 5)) # 1 + 5 = 6
((Number /= 2)) # 6 / 2 = 3
SecondNumber=2
Result=$((Number+SecondNumber))
echo $Result
$./script.sh
5

Conditions

Conditional statements are an important part of Bash Programming. They allow you to execute a block of instructions if, and only if, a certain condition is met. If that condition is not met, then another block of instructions is executed.

The syntax for this is really simple.

if "Condition"; then
 #Block
 #of
 #instructions
else
 #Another
 #Block
 #of
 #instructions
fi

Now, let’s try to make a statement with an actual condition. For this, we can use the test command that performs arithmetic and string comparisons, as well as checks on file attributes.

Arithmetic Comparisons

Here are the most common operators that you can use in arithmetic comparisons:

  • -gt : Greater than
  • -lt : Lesser than
  • -ge : Greater than or equal
  • -le : Lesser than or equal
  • -eq : Equal

Let’s test these :

Test 1 -lt 2 # Checks if 1 is lesser than 2, which is true
Test 5 -eq 9 # Checks if 5 is equal to 9, which is false

String Comparisons

Here are the most common operators to compare two strings of characters:

  • = : Equal
  • != : Not equal
  • -z : Length is zero
  • -n : Length is non-zero

Using these operators with actual strings, we get the following :

Test "Hello" = "Hello" # Returns true, since the two strings are identical.
Test -z "String Test" # Returns false, since the string length is not equal to zero.

Now,  let’s try to apply what we just learned in a more relevant example.

age=10;
threshold=18;
if test $age -lt $threshold; then
echo "You are still a minor."
else
echo "You are of legal age."
fi

To simplify this conditional statement even more, we can replace the command “test” with a pair of brackets, which do practically the same thing as test.

Here is the resulted code:

age= 10;
threshold= 18;
if [ $age -lt $threshold ]; then
echo "You are still a minor."
else
echo "You are of legal age."
fi

Before we close this section about conditions, you should note that you need to always separate the brackets from the condition using space. Otherwise, they won’t work. In addition, string variables should always be enclosed in double-quotes when included in conditions. This will make sure that they are processed correctly even if they include spaces.

Loops

Loops allow you to execute a block of instructions repeatedly.

The most common loop statement in Bash is using the ‘for loop’.

Here is the basic syntax :

for variable in {0..N}
do
 #Instructions to be repeated
done

Here, the loop will start by assigning the value of 0 to variable, and then executing the instructions to be repeated that are contained between the do and done keywords. After that, it will increment the variable value by 1, and then it will execute the instructions again. It will continue to do so until variable equals N. Finally, the loop will exit and the program will end or continue to the following instructions.

The following example shows how the variable value changes during the execution of the loop.

for i in {1..10}
do
echo "This sentence is being repeated $i times"
done

Running the above script will generate the following output.

This sentence is being repeated 1 times
This sentence is being repeated 2 times
This sentence is being repeated 3 times
This sentence is being repeated 4 times
This sentence is being repeated 5 times
This sentence is being repeated 6 times
This sentence is being repeated 7 times
This sentence is being repeated 8 times
This sentence is being repeated 9 times
This sentence is being repeated 10 times

At the above example, the variable increments its value by 1, we can change this by adding a step value as shown in the example below:

for i in {1..10..2}
do
echo "This sentence is being repeated $i times"
done

Here, the variable i will increment its value by two at each iteration.

This sentence is being repeated 1 times
This sentence is being repeated 3 times
This sentence is being repeated 5 times
This sentence is being repeated 7 times
This sentence is being repeated 9 times

Functions

We are going to finish this chapter with one last important feature of the Bash scripting language.

A function in Bash is a portion of a script or a set of commands that are defined only once, and then called during the execution of the program.

To define a function, you should start by typing the “function” keyword, followed by the name of the function. After that, you have to open curly braces, in which you are going to type in the commands when the function is called.

#!/bin/bash
function nameOfUser {
echo $(whoami);
}
nameOfUser

In the above example, the name of the function is nameOfUser. It contains only one command, which types the user profile that is running the program. This function is called once during the program execution, and below is the resulted output.

$ ./functions.sh
spect

Although this was a lengthy chapter, it didn’t cover many important elements about Bash scripting. But it should give you the basic foundation to start writing basic scripts.

With this chapter, we have closed the second part of this tutorial series. In the next chapter, we will embark on the third part in which we will explore the inner workings of Linux.

Tags:

Leave a Reply

Your email address will not be published. Required fields are marked *