Conquering the Terminal: An Introduction to Bash Scripting
Tags: bash, tutorial, programming
Published: 2024-05-12 22:43:42

The first encounter I had with the command line was at a relative's house many years ago. I was captivated by the sight of my relative effortlessly typing what seemed like cryptic commands onto a black screen. To me, that was the epitome of what a programmer looked like. Eager to explore this mysterious world, I rushed home and opened up the command prompt. With a mix of excitement and curiosity, I began typing commands that I had memorized, such as `cd` and `mkdir`, even though I didn't understand their functions at the time. However, these once-unfamiliar commands began to reveal their purpose and significance as I learned more about programming. Now, equipped with a better understanding, I'm thrilled to introduce you to the fascinating world of bash scripting. In this brief tutorial, I'll assume that you're already familiar with basic Linux commands like `echo`, `ls`, `cd`, `mkdir`, and `nano`.

Bash scripting allows you to unlock the true potential of the command line. 
Let's break things down. What does bash mean? 
Bash stands for Bourne-Again Shell. It is a command line interpreter It executes commands read from a standard input or a file. It's the default shell for most Unix-like operating systems, including Linux and macOS. 
Now what does scripting mean? 
Scripting is the process of writing and executing scripts using the Bash shell. A script is a series of commands and instructions that are written in a scripting language (in this case, Bash) and executed sequentially.

Time to create your first script
* Open any text editor. Create a file and name it anything with a `.sh` extension. For example, `myscript.sh`.
I am using Nano text editor. To open a new file on nano, type `nano <name of your file>` in your command prompt on your Linux or Mac, or WSL if you are using a Windows computer.

* The hashbang: The hashbang or the shebang is the first line of a bash script.  It consists of a hash character (`#`) followed by an exclamation mark (`!`). The shebang is then followed by the path to the interpreter executable. This shebang line tells the system to use the Bash interpreter located at `/bin/bash` to execute the script.
In a Bash script, it looks like this:

```
#!/bin/bash
```

Note also that a comment in Bash begins with the (`#`) symbol

* Basic "Hello World!": To display anything on the command line, we use the echo command.
```
#!/bin/bash

echo "Hello World!"
```

* Make the script executable: Before we can run this script, we have to grant it execute permission using the `chmod` command. Navigate to the directory where the script is stored and run the following:
`sudo chmod +x myscript.sh
`
Run `ls -l` and we'll see that the color of the file name is now green. Also, `rwxr` indicates that the user has read, write and execute rights.

![Executable and non-executable scripts](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/29wsvjd1brztot8cg2y2.png)


* Run the Script: Navigate to the directory containing your script and execute it using its filename. In your case:

`./myscript.sh
`
This is just a glimpse into the world of bash scripting. As you progress, you will explore variables, arithmetic operations, conditional statements, loops, and functions.

### Variables
Just like in other programming languages, a variable is a container that stores some data. Variable names in Bash consist of alphanumeric characters and underscores (a-z, A-Z, 0-9, _). They cannot start with a digit. Conventionally, variable names are written in uppercase, but this is not mandatory.
To assign a value to a variable, we use the `=` operator with no spaces around it.

```
#!/bin/bash

myvar=23
name="Ayo"
```
So, let's store "Hello World!" in a variable called `myvar` and display it on the screen.

```
#!/bin/bash

myvar="Hello World!"
echo $myvar
```
What's with the dollar(`$`) sign? 
To access the value stored in a variable, we prefix the variable name with a dollar sign. If you don't do that in the example above, "myvar" will be displayed instead of "Hello World!".
Feel free to try different examples in your text editor.

### Arithmetic Operations
Arithmetic operations are possible in almost all programming languages and Bash is no different. The table below shows some arithmetic operations and their symbols in Bash.

| Operation                  | Symbol |
|----------------------------|--------|
| Addition                   | `+`    |
| Subtraction                | `-`    |
| Multiplication             | `*`    |
| Division                   | `/`    |
| Modulo (Remainder)         | `%`    |
| Exponentiation             | `**`   |
| Increment                  | `++`   |
| Decrement                  | `--`   |

To write a simple math expression, we use the `expr` command. For example, 10 + 3 will be written as:

`expr 10 + 3
`
To store the result of an expression in a variable, we can use the double parenthesis: `$((...))`.

```
#!/bin/bash

result=$((10+3))
echo result
```
The result of the expression `10+3` is stored in `result` and the result of `13` is displayed.

Arithmetic operations with variables are also possible. Storing your values in variables before performing computation helps improve your code's readability and flexibility. Try the following example:
```
#!/bin/bash

num1=100
num2=4
result=$(($num1 % $num2))
# or result=$(expr $num1 % $num2)
echo $result
```
In the example above, we stored 100 and 4 in `num1` and `num2` respectively. We then performed the modulo operation which returns the remainder when `num1` is divided by `num2`: 100 % 4 which will give 0.

So now try this example: 100 divided by 3. Your answer should be 33.333..
```
#!/bin/bash

num1=100
num2=3
result=$(($num1 / $num2))
echo $result
```

Did you notice that the fraction part of the result was left out? This is because Bash primarily deals with integers. Bash stores numbers as integers and performs calculations with limited precision.
One solution to this is to use the `bc` command. Here's the same example you tried but using the `bc` command. You might need to install it if you get an error that `bc` command is not found. Install it using this command: `sudo apt-get install bc`


```
#!/bin/bash

num1=100
num2=3
result=$(echo "scale:3; $num1 / $num2" | bc)
echo $result
# 33.333 will be displayed
```
The `scale` keyword tells the computer how many numbers you want after the decimal.

### Bash Conditionals
Bash conditionals are fundamental constructs used for decision-making within Bash scripts. They allow you to execute different sets of commands based on whether certain conditions are true or false. The primary conditional statements in Bash are the `if`, `elif` (short for "else if"), `else`, and `fi` (which signifies the end of an if block) statements.

Before we see how these statements are used, take a look at the table below showing some important **numeric** comparison operators in Bash scripting. This will be useful later. 

| Name                | Operator |
|---------------------|----------|
| Greater Than        | `-gt`      |
| Greater Than or Equal To | `-ge` |
| Less Than           | `-lt`      |
| Less Than or Equal To | `-le`  |
| Equal To            | `-eq`   |
| Not Equal To        | `-ne`   |


Now open your text editor and write a script to read a number from a user and check if the number is even or odd. 
Haha! We haven't learned how to read user input yet. In bash, we use the `read` keyword. To display a prompt, we use the `read` keyword with a `-p` flag. Here's how it works:

```
#!/bin/bash

# Read a number from the user and display it:
read num
echo $num

# Prompt the user to enter a number and display it:
read -p "Enter a number: " num
echo $num

```
In both cases, the number is stored in the `num` variable

So, going back to your task, we read the number from the user and check if it's even or odd. Then, we print the corresponding message to the user:
```
#!/bin/bash

read -p "Enter first number: " num

if [ $(($num % 2)) -eq 0 ]; then
echo "Even Number"
else
echo "Odd Number"
fi
```

Do you understand the code? If you don't, not to worry. Here is a detailed explanation:
`read -p "Enter first number: " num`: This prompts the user to enter a number and stores the input in the variable `num`.
`if [ $(($num % 2)) -eq 0 ]; then`: checks if the remainder of dividing the number by 2 is equal to 0, indicating that the number is even.
`echo "Even Number"`: prints "Even Number" if the condition is true.
`else`: executes if the condition in the `if` statement is false.
`echo "Odd Number"`: Prints "Odd Number" if the number is not even.

###Loops
Just like other languages, loops allow you to execute a block of code multiple times.
Bash provides three primary loop statements; `for`, `while` and `until`. You'll explore the `for` and while `loops`.

#### The `for` loop:
The basic structure of a for loop is:

```
for item in ${list}; do
  # Commands to be executed for each item
done
```

Write a for loop to display all the numbers from 1 to 5.
```
#!/bin/bash
for i in 1 2 3 4 5; do
    echo $i
done
```

Another way to do it is by using the following format known as brace expansion:
`for i in {start..end..step}; do` or just `for i in {start..end}; do` if we want to display all the numbers from the start number to the end without any step.
```
#!/bin/bash

for i in {1..5}; do
    echo $i
done
```
In either case, your output should be:

![Output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fnsftofzz1dd50k1yok5.png)


To make your code more efficient, use an array to store the numbers and loop through the array.
```
#!/bin/bash

numbers=(1 2 3 4 5)

for i in ${numbers[@]}; do
echo $i
done
```

Okay, what's the `[@]` used for? 
`numbers[@]` is used to expand all the elements of the array and the for loop iterates through every element.

Write a Bash script to print out the ages of a person from 1 to 15, incrementing by 2 years for each age.
You can use the brace expansion method I explained previously:
```
for i in {1..15..2}; do
    echo "I am $i years old"
done
```

Another way to do this is by using the double parentheses.
`for ((initialization, condition, increment)); do
`

```
for ((i=1; i<=15; i+=2)); do
    echo "I am $i years old"
done
```
`for ((i=1; i<=15; i+=2))` has the following features:
* Initialization: `i=1` sets the initial value of the counter variable i to 1. 
* Condition: `i<=15` checks if i is less than or equal to 15. The loop continues as long as this condition is true. 
* Increment: `i+=2` increments the value of i by 2 in each iteration.

#### The `while` loop
**While** we've conquered iterating through predefined lists using the `for` loop 😂, Bash scripting offers another powerful tool for repetitive tasks: the `while` loop. Unlike the `for` loop, which thrives on a set list of elements, the `while` loop keeps executing a block of code as long as a specific condition remains true.

The format for a while loop is shown below:
```
while condition; do
    # Commands to be executed while the condition is true
done
```
Write a while loop to count down from 10 to 5.
* First define a `counter` (where you want to begin counting from)
* We want to decrement this `counter` by one during every iteration. So tell the computer that as long as `counter` is greater than or equal to 5, display its value and then decrement by one.
```
counter=10
while [ $counter -ge 5 ]; do
    echo "Countdown: $counter"
    ((counter--))
done
```
If you got it right, this should be your output:

![Output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aa90tx8cuwl4i2kavafa.png)


Do you have what it takes for the next task?
Write a script to retrieve input from a user until the user enters the string: `exit`.
Here's what to do.

1. Create an empty variable that will store the user input.
2. Write a while loop with a condition that the string value in the variable is not equal to "exit". 
3. `do`: read the input from the user.
4. `done`

```
user_input=""
while [ "$user_input" != "exit" ]; do
    read -p "Enter 'exit' to quit: " user_input
done

echo "Exit Successful"
```
So this is what the code does:
`user_input=""`: initializes the variable `user_input` to an empty string.
`while [ "$user_input" != "exit" ]; do`: starts a `while` loop that continues as long as the value of `user_input` is not "exit".
`read -p "Enter 'exit' to quit: " user_input`: prompts the user to enter a value and stores it in the variable `user_input`.
`echo "Exit Successful"`: Prints "Exit Successful" after the `while` loop exits, indicating that the user has entered "exit".

### Functions
Functions in programming allow you to encapsulate a sequence of commands into a reusable block of code. They improve code readability, maintainability, and reusability by breaking down complex scripts into smaller, more manageable pieces. 
As Martin Fowler aptly stated, 
> "Any fool can write code that a computer can understand. Good programmers write code that humans can understand."

You declare a function in Bash using the `function` keyword followed by the function name and parentheses.
```
function my_function() {
    # Function commands go here
}
```

Omitting the `function` keyword also works
```
my_function() {
    # Function commands go here
}
```

To invoke or call a function, you simply use its name
```
my_function() {
    # Function commands go here
}

# function call
my_function
```

Functions can have arguments. You'll learn a way of passing arguments to bash scripts and functions from the following example. 
```
greet() {
    echo "Hello $1, nice to meet you!"
}

greet "Dan"

```
What do we have here? 
In this example, the `greet()` function takes one argument, `$1`, which represents the first argument passed to the function. `$2` represents the second, `$3` represents the third, and so on.
When the function is called with `greet "Dan"`, the string "Dan" is passed as an argument to the function. Inside the function, $1 is replaced with the value "Dan".

So if you wanted to write a function to pass your name and age as parameters and display them in a string, your function would look like this:
```
myself() {
    echo "Hello I am $1, I am $2 years old"
}

myself "Fawz" 26
```
`$1` and `$2` are replaced by `Fawz` and `26` respectively.

####The `return` statement
Bash functions do not have explicit return types, but they can return a value using the return statement. The return value is stored in the special variable `$?`.

Write a function to add two numbers. Use the `return` statement to return the result. Remember that you will need to use echo to display the result stored in the `$?` variable.

```
function add() {
    result=$(( $1 + $2 ))  # Calculate the sum
    return $result  # Return the result
}

# Call the add function
add 5 3

echo "The sum is: $?"
# This will display "The sum is: 8"
```

## Conclusion and Further Exploration

Congratulations! You've successfully conquered the basics of Bash scripting. You've learned how to navigate the command line, write scripts to automate tasks, and control the flow of your programs using variables, conditionals, and loops. This newfound power opens doors to a vast world of possibilities, from automating repetitive tasks to managing complex system configurations.

But this is just the beginning of your Bash scripting adventure! You can check out the following resources to fuel your exploration:

* **Bash Guide:** The official Bash documentation is a comprehensive resource for everything Bash-related: [https://www.gnu.org/software/bash/manual/](https://www.gnu.org/software/bash/manual/) 
* **Free Bash Scripting handbook:**  This is an open-source introduction to Bash scripting guide/ebook that will help you learn the basics of Bash scripting:
[https://github.com/bobbyiliev/introduction-to-bash-scripting](https://github.com/bobbyiliev/introduction-to-bash-scripting)
* **Learn Bash Scripting:** This online tutorial offers a user-friendly introduction to Bash scripting concepts: [https://github.com/freeCodeCamp/learn-bash-scripting-by-building-five-programs/blob/main/TUTORIAL.md](https://github.com/freeCodeCamp/learn-bash-scripting-by-building-five-programs/blob/main/TUTORIAL.md)
* **Bash for Beginners:** This freecodecamp video provides a step-by-step approach to learning Bash scripting: [https://m.youtube.com/watch?v=tK9Oc6AEnR4](https://m.youtube.com/watch?v=tK9Oc6AEnR4)

Feel free to experiment, explore different scripts, and don't be afraid to make mistakes. The programming community is vast and welcoming, so don't hesitate to seek help online if you get stuck.

**Like and Comment!**

Did you enjoy conquering the terminal with this tutorial? If you found this introduction to Bash scripting helpful, or if you have any questions or suggestions, leave a comment below! I'd love to hear your thoughts and experiences. 
Thank you for reading!