# Shell/Bash Scripting - Let's write our first Bash Script

## Pre-Requisites to learn Bash/Shell Scripting:

* Linux basics
    
* Command line basics
    
* No programming knowledge required
    

## What is a Kernel?

Interface between hardware and software

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1720451100040/e5a3261c-4d28-46f1-ba67-6c2407a9a349.png align="left")

## What is a Bash/Shell?

* **Bash:** A command language interpreter used for interacting with a computer from the command line.
    
* It is like a container
    
* The interface between users and Kernel
    
* **Also Known As** Commonly referred to as "the shell."
    
* CLI is a shell
    
* **Purpose:**
    
    * Provides a user-friendly interface to interact with the operating system.
        
    * Hides the complex details of the operating system kernel.
        
    * Enables tasks such as accessing data and writing files through simple commands.
        
* **Historical Significance:**
    
    * Introduced in the early 1970s.
        
    * Revolutionized how users interact with computers.
        
* When you open any operating system like macOS or Linux's any distro like Ubuntu the default Shell is usually Bash.
    
* Bash is also a programming language that allows us to write scripts which means anything we manually type into the command line can be automated with code.
    

**Find your Shell**

* ```bash
        echo $0
    ```
    
* **Available Shells “cat /etc/shells”**
    
    ```bash
    cat /etc/shells
    ```
    
    * **Your Shell? /etc/passwd**
        
    
    ```bash
    cat /etc/passwd
    ```
    
* Windows GUI is a shell
    
* Linux KDE(K Desktop Environment.) GUI is a shell
    
* Linus sh, bash, etc. is a shell
    

## What is Bash/Shell Scripting?

A bash script is a file that contains one or more commands that are meant to be executed within your bash shell.

## Why Shell Scripting?

Shell scripts in Linux are an easy-to-use time-saving solution for automating repetitive or complex sets of tasks in a system administrator’s daily life. It can help save time and increase productivity, so it’s a must-have skill for anyone working on computers.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1720451678414/908fdc15-7c7b-4eb6-9589-42fad222d694.png align="left")

* Automate daily backups
    
* Automate installation and patching of software on multiple servers
    
* Monitor system periodically
    
* Raise alarms and send notification
    
* Troubleshooting and Audits
    
* Many more
    

## Types of Linux Shell

Below both of these are the desktop GUI environment

* Gnome
    
* KDE (K Desktop Environment)
    

**CLI environment:**

* **sh** - So, this just sh is a Bourne shell called sh, one of the original Linux shells. It is developed by Unix computers by Stephon Bourne. He worked for AT&T Labs in 1977. It offers features such as:
    
    * input and output redirection
        
    * shell scripting with string
        
    * integer variable and condition testing and looping etc…
        
* **bash** - It means Bourne again shell so it
    
* **csh and tcsh -** used specifically in cases if you are proficient with c/c++ languages. tcsh doesn’t run bash.
    
* **ksh -** KornShell( developed by David Korn). Korn shell is compatible with shell and bash shell as well. Korn Shell improves on Bourne Shell by adding floating point automatic job control.
    

## Best practice to follow:

* Give your script a name that makes sense.
    
* Design your script to be reusable
    
* The script should not require to be edited before running
    
* Use command line arguments to pass inputs.
    
* For example(good naming) create-and-launch-rocket
    
* Bad Naming: script1.sh, myscript2.sh, test.sh, etc…
    
* Leave out .sh extension for executables:
    
* good: create-launch-rocket
    
* bad: create-launch-rocket.sh
    

## Writing our first bash script:

```bash
#!/bin/bash

# A script that will print out a message

echo 'Hello Bash bro'
```

* **#!/bin/bash:** this line is called a **‘shebang’.** This is the line from where the script starts to execute[.](http://create-launch-rocket.sh)
    
* (hashtag or pound or number sign) !(exclamation mark) These together mean that hey, this is a **shebang.**
    
* **Shebang** is used to tell the environment we’re in, and which interpreter we will be using.
    
* In this case, since the shebang is /bin/bash, we’re telling it, hey, we’re going to use bash which makes sense because this is a bash shell.
    
* **#message:** with # (comment) is used to document your script, and provide clarity in context to what you’re creating here/what our program will do.
    
* **echo ‘Hello Bash bro’:** to print the output.
    

### How to execute a script

* First, make a file with the name you like. e.g.
    
    ```bash
    vi myscript
    OR
    vim myscript
    ```
    
* Give you file permission to execute:
    
    ```bash
    chmod a+x myscript
    # here a means to all users and x means execute
    ```
    
* **Execute Script Directly:**
    
    Run `./myscript` to execute the script.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1720452553741/a2698144-7e0c-4e72-9952-562f1d7ea685.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1720452581363/cf2c6c72-c049-409e-bcc0-5c05ce931b43.png align="center")

## What is a variable and how do we use them

A variable is a way to store data and use it within our bash script.

Why would you want to do this?

* Well, it makes us more efficient because we’re repeating less code.
    

**Variable** - whose values can change

**Constants** - whose value can not change

* Variable only contain Alphanumeric OR Underscores
    
* And it’s Case Sensitive as well
    

**Best practices:**

* good one: mission\_name
    
* bad one: Mission\_Name, Mission Name, Mission-name
    

```bash
#!/bin/bash

# This is when we assign value to a variable
hello_message='Hello, world!'

# If we want to print the current directory along with the message 
current_dir=$(pwd)

#  And this is when we are using variable
echo "$hello_message from $curret_dir"
```

## What are the positional arguments/parameters in shell scripting?

The positional parameters hold the arguments passed to a script or function. They are referenced using **$1, $2, $3, etc.**, where $1 is the first argument, $2 is the second, and so on. **$0 refers to the script's name**.

**Example script:**

```bash
#!/bin/bash 

echo "First argument: $1" 
echo "Second argument: $2
```

If the script is executed with `./myscript` arg1 arg2,  
it will output: First argument: arg1 Second argument: arg2

## How to accept user input

```bash
#!/bin/bash

echo Hello, My name is Suraj.
echo
echo What is your name?
echo 
read broname
echo
echo Hello $broname
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1720521229539/57397fe0-6a54-43ba-be71-879b8affbf2b.png align="left")

```bash
read -p "Enter mission name:" variable_name
echo $variable_name

# read take the input 
# -p display the text
```

## What are the conditional statements in bash?

Conditionals are just if else statements we can understand by the below example:

**A simple if-then code in bash**

```bash
#!/bin/bash

number=25

if [ $((number % 2)) -eq 0 ];
then
   echo "The number $number is even!";
else 
   echo "The number $number is odd!"
fi
```

```bash
#!/bin/bash

clear

if [ -e /home/devopsbro/basicbashscript/bro.txt ]

				then
				echo "File exists"
				else
				echo "File does not exist"
fi
```

## What are Case Statements in Bash?

Most of the installation programs are written in case statements where the scripts wait for user input to select from choices.

```bash
#!/bin/bash

# A script that will ask for a number and print out a message depending on the value. 

read -p "Enter a value: " n
case $n in
    ???) 
        echo "One";;
    2) 
        echo "Two";;
    aa) 
        echo "Three";;
    *.txt) 
        echo "Four";;
    *) 
        echo "Other";;
esac

# read: it is the command to ask the user to provide a number

# -p: allows us to provide a prompt which in this case is enter a value

# n: name of the variable
```

## What are loops in Bash?

* Program to automate the repeating task
    
* Here we are learning to **do while done** keywords
    

**While loop**

```bash
#!/bin/bash

# A script to display a series of numbers using a while loop.

counter=1
# here ‘ -le ‘ is less then
while [[ "$counter" -le 10 ]]; do
    echo "The counter is at: $counter"
    counter=$((counter + 1))
done
echo "The count has finished."
```

**Until loop**

```bash
#!/bin/bash

# A script to display a series of numbers using while.

counter=1
until [[ "$counter" -gt 10 ]]; do
    echo "The counter is at: $counter"
    counter=$((counter + 1))
done
echo "The count has finished."
```

**for loop traditional**

```bash
#!/bin/bash

# Print values in an array using for loops

services=("loadbalancer" "virtualmachine" "storage")

# here @ mean all the elements of the array services
for i in "${services[@]}"
do
   echo $i
done
```

**for loop new**

```bash
#!/bin/bash

# A script to display a series of numbers using a for loop.

for (( i=0; i<5; i=i+1 )); do
    echo "The counter is at: $i"
done
```

**loop and break**

```bash
#/bin/bash

# A script that will recieve input and break depending on condition. 

while true; do
# here n is variable that store the user input
  read -p "Enter a number between 1 and 25: " n
  if [[ $n -ge 1 && $n -le 25 ]]; then
    echo "You entered $n"
  else 
    echo "You didn't enter a number in range, goodbye."
    break
  fi
done
echo "Break happened"
# the ‘fi’ here is the opposite of ‘if’ to stop if statement
```

## What are the functions in bash?

A function in Bash is a reusable block of code that can be called with a name to perform a specific task, defined using the syntax `function_name() { commands; }`.

```bash
#!/bin/bash

# function name and definition
check_even () {
    local mod=2
    echo "The value of mod is $mod"
    if [ $(("$1" % $mod)) -eq 0 ]
    then 
       echo "The number $1 is even!";
    else 
       echo "The number $1 is odd!"
    fi
}
# Variable Declaration
number=2344

# Function Call
check_even $number
echo $mod
```

**local**: It is a scope here which means whatever is defined inside the function which {} can’t access outside but only inside.

## Check Remote Servers Connectivity

A script to check the status of remote hosts

```bash
#!/bin/bash

# this is a simple script
ping -c1 192.168.1.1
        if [ $? -eq 0 ]
        then
        echo OK
        else
        echo NOT OK
        fi

# Change the IP to 192.168.1.235
```

```bash
#!/bin/bash

# This is a good one
# Don't show the output
ping -c1 192.168.1.1 &> /dev/null
        if [ $? -eq 0 ]
        then
        echo OK
        else
        echo NOT OK
        fi
```

```bash
#!/bin/bash

# This is the better one
# Define variable

hosts="192.168.1.1"
ping -c1 $hosts &> /dev/null
        if [ $? -eq 0 ]
        then
        echo $hosts OK
        else
        echo $hosts NOT OK
        fi

# Change the IP to 192.168.1.235
```

```bash
#!/bin/bash

#Multiple IPs
IPLIST="path_to_the_Ip_list_file"


for ip in $(cat $IPLIST)

do
   ping -c1 $ip &> /dev/null
   if [ $? -eq 0 ]
   then
   echo $ip ping passed
   else
   echo $ip ping failed
   fi
done
```

# Aliases(alias)

In real life, aliases are short names of long ones to remember.

Aliases is a very popular command that is used to cut down on lengthy and repetitive commands

```bash
# Here are the some example of how you can make an alias of any command

alias ls="ls -al"
alias pl="pws; ls"
alias tell="whoami; hostname; pwd"
alias dir="ls -l | grep ^d"
alias lmar="ls -l | grep Mar"
alias wpa="chmod a+w"
alias d="df -h |awk '{print \$6}' | cut -cl-4"
```

**Note**: `{print \$6}` here before $6, we put backslash “\\” because we don't want Linux to not think of $6 as a variable.

* To know what and how many aliases you have made use the command `alias` to know.
    
* To delete an alias
    
    ```bash
    unalias nameOfAlias
    ```
    
* To delete all the aliases at once
    
    ```bash
    unalias -a
    ```
    

### User and Global Aliases

**Creating User or Global Aliases.**

* User = Applies only to a specific user profile
    
    ```bash
    User = /home/user/.bashrc
    ```
    
* Global = Applies to everyone who has an account on the system
    
    ```bash
    Global = /etc/bashrc
    ```
    

**Note**: So basically if we are creating an alias in the terminal without user-specific then it’ll stay only for that session and when you close and open the terminal you’ll not find the alias again. So to solve this we’ll be creating a user alias:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1720523543393/941c9750-a1a0-48bb-b20c-bc80b83105ea.png align="left")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1720523564768/f047f250-1f51-488c-b035-ebbc5d28317f.png align="left")

**Now let's make the alias Global:**

for me, this command works to add a global alias

```bash
sudo nano /etc/bash.bashrc
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1720523605242/9ff4afde-c12a-4e3b-87f1-af358f554ee4.png align="left")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1720523625522/2faf842d-3962-4427-9752-61d874652b22.png align="center")

## Shell History

You can know all the commands that you have run in your terminal by just running the command `history` .

```bash
history
```

If you want to scroll more command of history just run this command:

```bash
history | more
```

If you want to run any command from you history just remember the number of that command left side and run it this way:

```bash
!8
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1720523673975/33ddf783-c094-4d9a-b87c-f68a1dae99f2.png align="left")

**Note:** The file where the history of your shell commands is saved and to know that run the below command:

```bash
/home/username/.bash_history
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1720523720076/9726b4d1-6fb6-452d-b903-e6b91a385436.png align="left")

# The Linux commands you'll use while working with Bash

1. `ls --help` : To know more about ls command.
    
2. `echo --help` : To know more about echo command.
    
3. `man` : An interface to the system reference manuals.
    
4. `pushd` : Adds a directory to the directory stack.
    
5. `popd` : Removes a directory from the stack and changes to it.
    
6. `mkdir foldername` : Create the folder with the name specified.
    
7. `mkdir -p suraj1/suraj2/suraj3` : For creating parent directories.
    
8. `touch filename` : To create a file.
    
9. `mv source_name destination_name` : Used to move or rename files and directories from `source_name` to `destination_name` .
    
10. `cp source_name destination_name` : Copies `source_name` to `destination_name`, creating a duplicate file or directory.
    
11. `rm file_name_you_want_to_delete` : Used to remove files or directories.
    
12. `rm -r file_name_you_want_to_delete` : For recursive deletion
    
13. `rmdir directory_name` : Used to delete
    
14. `cat file_name` : Used to view to content of the file.
    
15. `head file_name` : This will display by default the first 10 lines of your content.
    
16. `head -n 5 file_name` : Now this will display the first 5 number of lines of your content because we have specified it using the ‘-n’ flag.
    
17. `tail file_name` : This will display by default the last 10 lines of your content.
    
18. `tail -n 5 file_name` : This will display the last 5 number of lines of your content.
    
19. `more file_name` : It will give the information page by page. and hit the space bar to go page by page.
    
20. `less file_name` : ‘less’ and ‘more’ are very similar just the less has a lot more options in its navigation.
    
21. `grep --help` : To know more about grep
    

**Use of Wildcards:**

* To find any files with an asterisk(\*) and with ??:
    
* To print all the files with the uppercase and lowercase as well:
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1720524789361/7ad17569-1ec8-4f13-8368-6c51d0c2f288.png align="left")

**How to use ‘whereis’ command:**

```bash
whereis file_name
```

```bash
whereis -b file_name
```

```bash
which file_name
```

**How to use the find command:**

```bash
find . -name "*.md"
```

The above command says to find in the current directory(.) all the name which has the .md extension

```bash
find /home -name file.txt
```

```bash
find /home -iname file.text
```

So here I mean it’ll remove the case sensitivity and show all the files whose name is file.txt regardless if it is in lowercase or uppercase

```bash
find . -type d
```

### How to use the environment variables command:

As the name suggests the environment variables set several variables for your shell environment. Environment variables are important because applications, command line tools, and shell scripts use them to determine their configuration.

* Knowing how to view, create, and modify environment variables is a must if you were to learn the ways of the terminal.
    

### The ‘env’ command:

this command will show you all the environment variables that are available currently.

```bash
env
```

* If we want to see just a single environment variable, we can use the ‘echo’ command:
    

These are the environment variables:

```bash
echo $SHELL
# OUTPUT: /bin/bash
```

```bash
echo $HOME
# /home/user
```

```bash
echo $USER
# user
```

```bash
echo $PATH
# (example): /home/devopsbro/.nvm/versions/node/v20.15.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin
```

### The command to create an environment variable is ‘export’:

`export --help` : To know more about export command.

```bash
export newVar=value
echo $newVar

# output: value
```

**Important**: The environment variable that we just created is only for the current session. And the question comes in :

**“How do you persist environment variables across sessions?”**

and “the answer to this question is what bash calls **startup files**.”

* So there are several locations for the **startup files** but two worth mentioning are the **‘global configuration’** which is located under the ‘etc’ profile, and if you were to make changes to this particular file, it would affect every user logged in to the machine or their bash session for every user logged in the machine.
    

```bash
ls /etc/profile
```

* Another one is the ‘.’ profile which exists underneath the user’s home directory
    

```bash
ls -a ~

# it will output: .bashrc or .profile kind of profiles
```

## How to use Redirection:

Everything that you see on the terminal either comes from an output stream or an input stream. In bash, you can redirect or chain together that output using the redirection operator and the pipeline.

* One of the streams that command right to is the standard output:
    
    ```bash
    ls - l
    ```
    
* Using redirection operator now:
    
    ```bash
    ls -l > file_name.txt
    ```
    
* If you want to put the new content in a new like you want to append:
    
    ```bash
    touch file_name.txt
    ls -l >> file_name_in_which_you_want_to_apppent.txt
    ```
    

### Standard error:

```bash
ls -l ./dir

# This will give an error
```

**Here 2 is the file descriptor** that indicates the standard error, and so it’s saying redirect standard error to this particular location.

```bash
ls -l ./dir 2> error.txt
```

Now, this is without a file descriptor:

```bash
ls -l ./dir > error.txt

# It just redirects to the terminal because I'm not redirecting standard error, I am trying to redirect the standard output
```

So here 2&gt;&1 in this we’re saying stream one and stream two redirects to these files.

```bash
ls -l ./dir > error.txt 2>&1
or 
ls -l &> error.txt 

# The above two commands are the same as long as we're doing this is in the same directory but not append.
```

If we want to append we can do this:

```bash
ls -l >> error.txt 2>&1
```

### How to use pipelines ( | ):

This is without the pipe symbol

```bash
ls -l /usr/bin
```

as we know what `less` command do this will show the content less and we can scroll using the spacebar

```bash
ls -l /usr/bin | less
```

This will find the echo in this directory

```bash
ls -l /usr/bin | grep echo
```

This will find and sort the content

```bash
ls -l /usr/bin | grep echo | sort
```

This will show the first content of this file.

```bash
ls -l file_name.txt | head -n 1
```

This will show the last line of the file.

```bash
ls -l file_name.txt | tail -n 1
```

## How to modify file permissions in Bash:

**How to view permissions:**

```bash
ls -ltr or
ls -l
```

Command to change the owner for Ubuntu users:

```bash
sudo chown root file_name.txt
# Here chown is the command and root is the new owner and the file name whose owner you want to change.
```

```bash
sudo chown :root file_name
# This command is used for changing the group owner
```

```bash
chgrp owner_name_you_want_change file_name
# This is the another command to change the group owner
```

### How to use the chmod command:

This command will add the execute permission to the file for user, group, and other

```bash
chmod +x file_name
```

```bash
chmod 444 file_name
# The 444 means here in the user,group,and other it will give permission to execute the file.
```

Afterward, executing `ls -l file_name` might show something like:

```bash
-r--r--r-- 1 user group 1234 Jul 9 10:00 file_name
```

**This table will help you to understand better:**

| Octal Number | Permissions | Meaning |
| --- | --- | --- |
| 0 | \--- | No permissions |
| 1 | \--x | Execute only |
| 2 | \-w- | Write only |
| 3 | \-wx | Write and execute |
| 4 | r-- | Read-only |
| 5 | r-x | Read and execute |
| 6 | rw- | Read and write |
| 7 | rwx | Read, write, and execute |

# Best Resources from where I learned

**YouTube Video Resources:**

1. [Bash in 100 Seconds By Fireship](https://www.youtube.com/watch?v=I4EWvMFj37g)
    
2. [Shell Scripting Zero To Hero || Shell Scripting for Devops & Cloud || Shell scripting for Beginners](https://www.youtube.com/watch?v=ldqmDIexAsA)
    
3. [Welcome to Bash for Beginners \[1 of 20\] | Bash for Beginners](https://www.youtube.com/watch?v=nrfwcbYJZfc&list=PLlrxD0HtieHh9ZhrnEbZKhzk0cetzuX7l)
    

> Thanks for reading guys
