Getting started with bash scripting
Tags: bash, linux, programming, productivity
Published: 2023-05-24 05:33:00

A bash script is a series of commands written in a file, which is read and executed by the bash program. The program executes line by line. For example, if you have multiple bash commands that you want to run, you can compile these commands into a bash script instead of typing and executing the commands manually one by one.

You can do the same sequence of steps by saving the commands in a bash script and running it. The script can be run any number of times without having to retype it.

These commands are a mixture of commands we would normally type ourselves on the command line (**ls, cp, cat, awk**).

Anything that you normally do on the command line can be put into a bash script and it will do the same thing.

**Reasons to learn bash scripting**
**1. Flexibility**
With Bash Scripting, you will be more flexible to use the terminals more often, rather than clicking upon GUIs.
**2. Less Resource-Intensive:**
Learning bash scripting and using the command line maximizes your speed when you lack computing resources.
**3. Accessibility**
Bash scripts can be created and executed by anyone with a basic understanding of the command-line interface.

In this guide, we will explore bash scripting and its features. Here, you will learn
- How to create a bash script and execute it.
- The basic syntax of shell scripting.
- Creating Variables
- Comments
- Define Functions
- Create Loops
- Conditional statements
- Defining Arrays

**What you should know**
- How to Use Unix/Linux shell
- Familiar with Linux or Unix commands. Some of the common commands include grep, ls, echo, date, cd, cat, etc
- Minimal programming knowledge - Understands variables, functions, etc.

A bash script tells the bash shell what to do. **A bash script is a useful way to group commands to create a program.** Any command you could execute directly from the command line can be put into a bash script, and you could expect it to do the same actions as it would from the command line.

**Identifying a Bash Script**
By naming conventions, bash scripts end with a .sh. Although, sometimes the .sh extension can be removed and the script will run perfectly fine.

Scripts start with a shebang
```bash
#!/usr/bin/bash
```
The beginning of a script file is identified with a shebang. This is the first line of the script. Shebang tells the shell to execute it via bash shell. Shebang is simply an absolute path to the bash interpreter.
Formatting is important here. The shebang must be on the very first line of the file.
There must also be no spaces before the # or between the ! and the path to the interpreter.

To know the shell interpreter you are using
```bash
echo $0
```
![shell interpreter](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4x6cj6jwc5kuisjx9hwd.png)

To check the list of available shells on your Unix operating system:
```bash
cat /etc/shells
```
![list available shell](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ptzo2tsyj9l86wka0kl.png)

Let's create a simple script in bash that outputs Hello World.
Create a file named hello_world.sh

```bash
touch hello_world.sh
```
find the path to your bash shell
```bash
which bash
```
![location of shell interpreter](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y4y1kihekcxdw0es4ank.png)

Place the outputted path on the top of your script.
```bash
#!/usr/bin/bash

echo "Hello World"
```
**Run the script.**
You can run the script in the following ways:
```bash
bash hello_world.sh
```
```bash
./hello_world.sh
```
With the second option, bash outputs a permission denied error message.
![run bash script](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cuwahsbaazuvzmmyc6di.png)

The reason for this is because of execution rights. Scripts have execution rights for the user executing them.

```bash
ls -l hello_world.sh
```
An execution right is represented by x. To give execution rights to the user.
```bash
chmod +x hello_world.sh
```
chmod modifies the existing rights of a file for a user.
![set user permission on file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n5cjb3ov1i3t2vvcbo0d.png)

Now execute the file again
```bash
./hello_world.sh
```
**Creating Comments**
Comments are lines that aren't executed by the interpreter
**Single-line comments:**
```bash
# This is a comment
```
**Multi-line comments**

```bash
: "The following is a 
Multi-line comment "
```

**Defining Variables**
variable=value
Note that there must be no spaces around the "=" sign: variable=value works; variable = value doesn't work
```bash
#!/usr/bin/bash

GREETING="Hello World"
echo $GREETING
```

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

message="Learning Bash Scripting"
echo $message
```
Shell scripting adheres to case sensitivity. If you define your variables in uppercase or lowercase, you must consistently use uppercase and lowercase letters.

You should always make sure variable names are descriptive. This makes them easier for you to remember and their purpose known.

Variables in the bash shell do not have to be declared, as is the case in other languages like Python, etc, where the variable has to be declared before they are accessed.
If you try to read an undeclared variable, the result is an empty string.

```bash
#!/usr/bin/bash
message="Learn Bash scripting"
echo $mesage
```
Notice the omission of an s from the variable name. The program still runs but returns an empty string.

**Ask the User for Input**
If we would like to ask the user for input then we use a command called read. This command takes the input and will save it into a variable.
```bash
#!/usr/bin/bash
echo what is your name?
read name
echo $name
```
If you would want to include an inline message with the variable, use the -p flag.

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

read -p "what is your name " name

echo $name
```
Adding -s makes the user input silent. That is, the input won't be shown when typed.

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

read -sp "Enter your password " password
echo $password
```
You can also ask the user for multiple input

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

read -p "What are your two favorite colors " color_1 color_2

echo "color_1 is $color_1"
echo "color_2 is $color_2"
```
Using command line arguments

```bash
#!/usr/bin/bash
echo $1 $2
```
```bash
./hello_world.sh Learning Bash
```
This also serves as a way to get inputs from the user. $1 represents the first argument. $2 represents the second argument.

This also serves as a way to get inputs from the user. $1 represents the first argument. $2 represents the second argument

**Other Special Variables**
Some system-defined variables include:
**$0** - The name of the Bash script.
**$1 - $9** - The arguments to the Bash script.
**$#** - The number of arguments passed to the Bash script.
**$@** - All arguments supplied to the script.

**Perform Mathematical Calculations**
Performing mathematical calculations can be easily done in bash scripts using different methods.

```bash
expr 2 + 3 

expr 3 * 5
expr 4+4
```
This expression will return as is without performing a calculation.
All mathematical operators can be used here + - / * % etc.

let is a built-in function of Bash that allows us to do simple mathematical calculations. 
let is a built-in function of Bash that allows us to do simple mathematical calculations.
```bash
let a=4+5

echo $a
```
**Note here that there is no space between the values.**
To add spaces, a quote can be used. A single or double quote is preferred.

```bash
let "a = 6 + 6"

echo $a
```
Mathematical expressions can also be stored using the syntax below

```bash
var=$((expression))  

var=$((3+9))

echo $var
```
With this method, $((expression)), decimal calculations aren't done properly.
bc command is used to perform the right decimal calculation
```bash
echo "scale=2 10/3" | bc
```
scale defines the number of decimal places required.

**Creating functions**
The purpose of writing functions is to avoid writing the same code constantly, and it also makes your code more readable.

```bash
example_function () {
  commands
}
```
Another method to create a function is to begin the line with the reserved bash keyword: function, then the function name and curly braces for the function body - we do not need the parentheses.


```bash
# Another way to write a bash function.
function example_function {
  commands
}
```
Defining the function will not execute the commands. To invoke a function, you must call the function name, as follows:

```bash
#!/bin/bash

# A hello world bash function
hello_world () {
  echo "Hello World!"
}

# Invoking the hello_world function
hello_world
```
**Passing arguments to functions**
Arguments are variables used in a specific function.
In shell scripts, we cannot pass arguments to functions like you would in other programming languages such as Python, etc.
Instead, shell functions have their command line argument and we can pass parameters to a function by placing them after a call to the function.

```bash
#!/bin/bash
greeting () {
  echo "Hello $1 $2"
}

greeting "Mark" "Joe"
```
**Writing "If" Statements**
"If" statements are conditional statements used to determine whether a command will run or not. If a statement is proven to be true, then a condition would run, else it is skipped.
Conditional statements begin with an if statement and ends with fi (if spelled backward).

```bash
#!/bin/bash
read -p "What is the secret number: " number

if [ $number -eq 10 ];
then
  echo "Your guess is right. The secret number is $number"
fi
```
Sometimes, based on a given input you would love to return a different output. The if-else statement is used.

```bash
if [ condition ]
then
  statement
else
  do this by default
fi
```
You may have multiple conditions to perform.

```bash
if [ <some test> ]
then
 <commands>
elif [ <some test> ] 
then
  <different commands>
else
 <other commands>
fi
```
**Multiple Conditions with Boolean Operators**
Sometimes you only want to take an action when multiple conditions are met. Other times you would like to act if one condition is met at least. This can be achieved with Boolean operators
**and - &&**: Multiple conditions must be met
**or - ||**: At least, a single condition is met.

```bash
if [$age < 18] || [$age > 50]
then
  echo "Not allowed to party"
fi
```
You can also do this

```bash
if [ $age -gt 18 -a $age -lt 50 ]
then
  echo "Allowed to party"
fi

if [ $age -lt 18 -o $age -gt 50 ]
then
  echo "Not Allowed to party"
fi
```

**-a** is similar to **&& (And)**
**-o** is similar to **|| (Or)**

**Case Statement**
If you want your program to take different paths based on different variable-matching, case statements to the rescue.

```bash
case $INPUT_STRING in
hello)
  echo "Hello!"
  break
  ;;
hi)
  echo "hi!"
  break
  ;;
*)
  echo "Sorry, I don't understand your greeting"
  ;;
  esac
```
**Loops**
Loops are useful if you want to execute commands multiple times. The available loops include- for, while, and until.
The for loop runs the command for a list of items:

```bash
#!/bin/bash

for item in [list]
do
  [commands]
done
```
This example uses a for loop to print the days of the week:

```bash
#!/bin/bash

for days in Monday Tuesday Wednesday Thursday Friday Saturday Sunday
do
echo "Day: $days"
done
```
**While Loop**
The script will evaluate a condition. If the condition is true, it will keep executing the commands, when the condition becomes false, it will stop the execution.

```bash
#!/bin/bash
while [condition]
do
[commands]
done
```
```bash
#!/bin/bash
counter=0
while [ $counter -le 10 ]
do 
  echo $counter
  ((counter++))
done
```
**Until Loop**
The opposite of the while loop. It will continue executing the command until the condition becomes true.

If we want the same output as the while example above using the until loop, we can write the script like this:

```bash
#!/bin/bash

counter=0

until [ $counter -gt 10 ]
do
  echo Counter: $counter
  ((counter++))
done
```
**Select Loop**
Allows you to create a simple menu.

```bash
select var in <list>
do
<commands>
done
```
```bash
names='Monday Tuesday Wednesday Thursday Friday Saturday Sunday None'

select name in $names 
do 
if [ $name == 'None' ] 
then 
break 
fi 
echo Hello $name 
done
```
**Extras**
**Range Calculation**

```bash
for value in {1..5} 
do 
  echo $value 
done
```
**Break and continue**
A break statement is used to exit from a running program while continue is used to skip the current iteration and move to the next one.

```bash
for value in 1,2,3,4,5
do 
if [ $value == 3 ] 
then 
continue 
fi 
  echo $value
done
```

```bash
#!/bin/bash

for value in 1 2 3 4 5 
do 
if [ $value == 3 ] 
then 
break
fi 
  echo $value

done
```
**Arrays**
When working with a large amount of data, it is very helpful to initiate the use of arrays.
There are two types of arrays that we can work with, in shell scripts.
**Indexed Arrays** - Store elements with an index starting from 0
**Associative Arrays** - Store elements in key-value pairs

The default array that's created is an indexed array
To create an indexed array, you use the declare command with the -a option

```bash
declare -a indexed_array

indexed_array = (1,2,3,4,5)
indexed_array[0]
```
To display all the values of an array we can use the following shell expansion syntax

```bash
echo ${indexed_array[@]}
```
**Associative Array**
To declare an associative array, use the -A option

```bash
declare -A associative_array
associative_array=([foo]=bar [baz]=foobar)
```
Note that you can create arrays without the declare keyword, but for associative arrays, when using the declare keyword, the -A is a must.

```bash
indexed_array=("first" "second")
associative_array=([first]="first goal" [second]="second goal")

# Print all elements
echo ${associative_array[@]}
echo ${indexed_array[@]}
```
**Getting the number of elements**
We can retrieve the number of elements contained

```bash
echo "the array contains ${#indexed_array[@]} elements"
echo "the array contains ${#associative _array[@]} elements"
```
**Adding elements to an array**
You can add elements to an indexed or associative array by specifying respectively their index or associative key

`indexed_array = (1,2,3)
indexed_array+= (9)`

To add elements to an associative array, you have to specify their associated keys:

```bash
declare -A associative_array

# Add single element
$ associative_array[foo]="bar"

# Add multiple elements at a time
associative_array+=([baz]="foobar" [john]="doe")

# Acceesing elements in an array
echo ${associative_array[foo]}
```
**Deleting an element from an array**
To delete an element from the array, use the unset command. But you need to know its index or its key in the case of an associative array.

```bash
unset indexed_array[0]
unset associative_array[foo]
```

**Delete the entire array**
```bash
unset indexed_array
unset associative_array
```
**Conclusion**
A bash script is a series of commands written in a file. bash scripts can be used to replace any operation that you can perform on the terminal.

In this tutorial, you were introduced to how to create a bash script, write loops, define functions, and declare arrays.
Understand that any command that you can type manually in your terminal can be used inside a bash script.

This tutorial has aimed to get you up and running with writing shell scripts. There is still a lot of learning to do when it comes to using bash scripts.

I hope you now have an understanding of writing bash scripts and have it can help you automate your workflow and make you productive.

Connect with me on [Twitter ](twitter.com/aviatorIfeanyi) or [Linkedin](https://www.linkedin.com/in/aviatorifeanyi/)