Module-0 Introduction to Bash scripting

Table of Contents

Introduction

Wondering how to do the bash scripting for automating your day to day tasks? We got you covered through this series of training on bash scripting. 

In this article we will be going through some fundamentals to know before getting into advanced bash scripting 

What is a Shebang or hashbang (#! )

Shebang or hashbang  #!  present on the head of the script tells which interpreter to be used. Here are some examples hashbangs you will see in bash scripts

#!/bin/bash   - denotes using Bash shell ( Bourne Again SHell) as interpreter 
#!/bin/sh    - denotes using Bourne shell 

Please note that bash and sh are different shells . Typically we can call  Bash is a shell with more features than the  sh shell

If we are willing to use python as interpreter , we can do the following 

For python3 

#!/usr/bin/env python3

For python 2

#!/usr/bin/env python2

Following to be used only when the script you are writing is compatible for both python 2.x and python 3.x 

#!/usr/bin/env python

 Do not use the following as we may see some differences in the location of the python install 

#!/bin/python 

Or 

#!/usr/local/bin/python

Here are few other examples on the Hashbang to use other interpreters 

For perl scripts 

#!/usr/bin/env perl

For ruby scripts 

#!/usr/bin/env ruby

For sed and awk scripts you can use the following hashbangs

#!/usr/bin/sed -f

#!/usr/bin/awk -f

How to create a basic bash script

Now let’s dive into creating the bash script file and executing it 

Here is a example of a basic bash script where we are using the well known echo command to print a text “this is a bash script“ 

[root@discoveringsystems Bash-Scripting]# cat bash_script
#!/bin/bash

echo " this is a bash script "

Currently we can see that the bash_script file doesn’t have execute permission 

[root@discoveringsystems Bash-Scripting]# ls -l bash_script
-rw-r--r--. 1 root root 45 Jan 20 11:42 bash_script

So we get the following error when trying to execute it by using the shebang to automatically assign the interpreter as bash 

[root@discoveringsystems Bash-Scripting]# ./bash_script
bash: ./bash_script: Permission denied

Then we changed the file permission to make it a executable file for bash 

[root@discoveringsystems Bash-Scripting]# chmod 744 bash_script

[root@discoveringsystems Bash-Scripting]# ls -l bash_script
-rwxr--r--. 1 root root 45 Jan 20 11:42 bash_script

After providing the permission this worked now 

[root@discoveringsystems Bash-Scripting]# cat bash_script
#!/bin/bash

echo " this is a bash script "


[root@discoveringsystems Bash-Scripting]# ./bash_script
 this is a bash script

How to use Special Characters in Bash Scripts

In this section we will be covering some special characters used in the bash scripts to make things easier for you to get used to writing bash scripts 

Comment (#)

Comments will not be executed as part of the script. However they are helpful to write some notes on the function of a particular block of the script. Here are some examples to comment on the script 

[root@discoveringsystems Bash-Scripting]# cat bash_script
#!/bin/bash

#first comment
  #second comment
echo " this is a bash script " # 3rd comment

While executing we were able to see that the comments were ignored. Also note the different places we can comment on a script , I have commented in a way that covers some of the possible places to comment on the script. 

[root@discoveringsystems Bash-Scripting]# ./bash_script
 this is a bash script

Command separator (;)

It helps adding two or more commands on the same line. For example, 

[root@discoveringsystems Bash-Scripting]# cat bash_script
#!/bin/bash

echo "one" ; echo "two" ; echo "three"

[root@discoveringsystems Bash-Scripting]# ./bash_script
one
two
three

Dollar sign for Variable substitution ($) 

We can use the dollar sign ($) for variable substitution in bash scripts . For example, 

[root@discoveringsystems Bash-Scripting]# cat bash_script
#!/bin/bash

var_name="one"

echo "$var_name"

[root@discoveringsystems Bash-Scripting]# ./bash_script
one

Escape character ( \)

Using the escape character we can skip processing of  other bash special characters. For example , in the below example scripts , the Dollar sign was used to call the defined variables, However I used the “\” to escape treating it as the bash special character and we can see that the variable is not called. 

#without using the escape character

[root@discoveringsystems Bash-Scripting]# cat bash_script
#!/bin/bash

var_name="one"

echo "$var_name" ; echo "two" ; echo "three"
[root@discoveringsystems Bash-Scripting]# ./bash_script
one
two
three


# using the escape character in this script 

[root@discoveringsystems Bash-Scripting]# cat bash_script
#!/bin/bash

var_name="one"

echo "\$var_name" ; echo "two" ; echo "three"

[root@discoveringsystems Bash-Scripting]# ./bash_script
$var_name
two
three

Single Quotes (‘  ’) and Double Quotes (“  “)

Using the single quotes we can preserve bash special characters within the quotes ,that means it can literally be interpreted as the strings. Double Quotes can be used for the strings which contain spaces and some special characters used within the double quotes are processed by the bash. Here is the example for using both singles quotes and double quotes within bash script 

[root@discoveringsystems Bash-Scripting]# cat bash_script
#!/bin/bash

var_name="one"

echo '$var_name' ; echo "$var_name and two and three"

[root@discoveringsystems Bash-Scripting]# ./bash_script
$var_name
one and two and three

Arithmetic expansion (( ))

This is used within the scripts to deal with expressions and calculations. Here is the example for arithmetic expansion use in the bash scripts

[root@discoveringsystems Bash-Scripting]# cat variable_test.sh
#!/bin/bash

Number=1

value=$((Number+Number))
echo $value

[root@discoveringsystems Bash-Scripting]# sh variable_test.sh
2

Redirections

Stdout is file descriptor 1 and the stderr is file descriptor 2. Using redirections, we can redirect these streams to a file instead of getting printed on the terminal

>

Redirects the stdout to a file , if that file is not present it creates a file. If the file is present it just overwrites the contents of the output to the file . Using “>” is same as using the “1>” as it redirects the stdout( file descriptor 1) 

[root@discoveringsystems Bash-Scripting]# echo "this is a redirection file" > redirection_file

[root@discoveringsystems Bash-Scripting]# cat redirection_file
this is a redirection file

[root@discoveringsystems Bash-Scripting]# echo "this is an overwrite example" > redirection_file

[root@discoveringsystems Bash-Scripting]# cat redirection_file
this is an overwrite example
>>

This only appends the output to the file , doesn’t do the overwrite. In the following example we are going to append some text to the file


 [root@discoveringsystems Bash-Scripting]# cat redirection_file
this is an overwrite example

[root@discoveringsystems Bash-Scripting]# echo "this is an append example" >> redirection_file

[root@discoveringsystems Bash-Scripting]# cat redirection_file
this is an overwrite example
this is an append example
&> and &>>

This redirects both the  stdout and the stderr of the command to the file . You can use both the redirects with either overwrite (&>)  or redirect with append (&>>)

Here is an example to understand the &> and &>>.  I am going to use the sleep command to explain both the stdout and stderr redirection 

# The command errored out so it prints stderr
[root@discoveringsystems Bash-Scripting]# sleep
sleep: missing operand
Try 'sleep --help' for more information.

#The command worked this time so stdout is displayed , for working Sleep command the stdout is null 
[root@discoveringsystems Bash-Scripting]# sleep 1
[root@discoveringsystems Bash-Scripting]#

# Command failed and the stderr is redirected to a file 
[root@discoveringsystems Bash-Scripting]# sleep &> redirect_file
[root@discoveringsystems Bash-Scripting]# cat redirect_file
sleep: missing operand
Try 'sleep --help' for more information.

# command worked and the stdout is redirected to a file 
[root@discoveringsystems Bash-Scripting]# sleep 1 &> redirect_file
[root@discoveringsystems Bash-Scripting]# cat redirect_file
[root@discoveringsystems Bash-Scripting]#

Similarly we can also do the append

[root@discoveringsystems Bash-Scripting]# sleep  &>> redirect_file

[root@discoveringsystems Bash-Scripting]# cat redirect_file
sleep: missing operand
Try 'sleep --help' for more information.

[root@discoveringsystems Bash-Scripting]# sleep 1  &>> redirect_file

[root@discoveringsystems Bash-Scripting]# cat redirect_file
sleep: missing operand
Try 'sleep --help' for more information.
2>&1

This is used to redirect the stderr to stdout . Here in this example , we know that date “test” will error out , so we are redirecting the stderr to stdout and then redirecting the stdout to a file. 

[root@discoveringsystems Bash-Scripting]# date "test"  1> redirect_file 2>&1

[root@discoveringsystems Bash-Scripting]# cat redirect_file
date: invalid date ‘test’
1>&2

This is used to redirect the stdout to stderr . Here in this example , we know that the working “date” command will print stdout   , so we are redirecting the stdout to stderr and then redirecting the stderr to a file.

[root@discoveringsystems Bash-Scripting]# date  2> redirect_file 1>&2
[root@discoveringsystems Bash-Scripting]# cat redirect_file
Wed Jan 25 10:43:53 EST 2023

|  Pipe

This passes the stdout of one command to the stdin of the next command. For example we can see that the stdout from the ls -l is piped to the grep command as the stdin so that it can produce filtered stdout as a result and print on the terminal 

[root@discoveringsystems Bash-Scripting]# ls -l | grep -i bash
-rwxr--r--. 1 root root  85 Jan 23 10:39 bash_script

&

It is used to run a command or script as a background process. In this example we were running tail forever for the /dev/null file and made it to run in the background 

[root@discoveringsystems Bash-Scripting]# tail -f /dev/null &
[1] 97904

[root@discoveringsystems Bash-Scripting]# jobs
[1]+  Running                 tail -f /dev/null &

We can bring that process to foreground using the “fg <job number from jobs output> “. I killed the process after bringing it to the foreground 

[root@discoveringsystems Bash-Scripting]# fg 1
tail -f /dev/null

^C
[root@discoveringsystems Bash-Scripting]# jobs
[root@discoveringsystems Bash-Scripting]#

$? 

This is used to get the exit value of the previous command 

In the following example , the date command errored out , when checking the exit value we found it to be 1 which means unsuccessful 

[root@discoveringsystems Bash-Scripting]# date "test"
date: invalid date ‘test’
[root@discoveringsystems Bash-Scripting]# echo $?
1

In this example , the date command worked , when checking the exit value we found it to be 0 which means successful 

[root@discoveringsystems Bash-Scripting]# date
Wed Jan 25 11:03:16 EST 2023
[root@discoveringsystems Bash-Scripting]# echo $?
0

Exit status in the Bash is an integer and You can see  non-zero exit status ranges ( 1-255 ) , which  indicates a failure . By using this exit status as conditionals ( if ) in the scripts we can validate a command working while running scripts and based on that do further processing 

How to Deal with the arguments in bash scripts

Bash has some inbuilt variables to deal with the argument provided along with the script. Through the example script , let me explain the different things we can do with those. 

$#    helps getting the total number arguments provided along with the script 
$@  helps getting all the variables passed along with the script as an array 
$*    helps getting all the variables passed along with the script as a single string  
$1   helps to use the first argument passed with the script 
$2   helps to use the second argument passed with the script 
Likewise we can do $3 or more if we have many arguments passed with the script 

[root@discoveringsystems Bash-Scripting]# cat bash_script
#!/bin/bash


echo "first argument is $1"
echo "second argument is $2"
echo "total number of arguments is $#"
echo "here is the actual arguments passed while running the script as an array : $@"
echo "here is the actual arguments passed while running the script as a single string : $*"

[root@discoveringsystems Bash-Scripting]# ./bash_script one two
first argument is one
second argument is two
total number of arguments is 2
here is the actual arguments passed while running the script as an array : one two
here is the actual arguments passed while running the script as a single string : one two

Leave a Comment

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