Search
Close this search box.

What Is A Bash Script? A Beginner’s Guide To Bash Scripting

If you are a system administrator responsible for maintaining tens or hundreds of Linux servers, manually updating each server or applying configurations would not only be time-consuming but also prone to errors. This is where Bash scripting comes in handy. You can write a script to automate updates, backups, or configurations across multiple servers simultaneously.

For instance, instead of logging into each server individually, a single Bash script could remotely log in, apply updates, and even send notifications of completed tasks. Wonderful, isn’t it. But if you are a beginner starting your Linux journey, you might have a question like “What is a Bash Script?” or “How Bash Scripting Can Help Automate Things?”

In this guide, we will start with the basics and understand Bash Script, syntax and key concepts of Bash Scripting, and even some practical examples.

What Is A Bash Script?

Bash, short for “Bourne Again Shell,” is one of the most popular and widely-used shell or command-line interfaces (CLI) in Unix-based and Unix-like systems (including Linux). It is based on the Bourne Shell (simply known as sh). The purpose of Bash (or any shell for that matter) is to provide a text-based interface (nowadays graphical user interface as well) for the user to interact with the system.

When we say “interact”, it can be anything: typing on the keyboard puts letters on the screen, moving the mouse will change the position of the cursor, or a simple command to delete a file will clear the bytes on the hard disk.

Apart from system interaction, Bash has one other important functionality: the ability to execute commands in a sequence, with or without user interaction. The file that contains this series of commands is known as a Bash Script.

Most Linux distributions come pre-installed with Bash. As a result, Linux users (regular users as well as system administrators) can automate nearly any task performed in the terminal by using Bash scripts. Whether it is file manipulation, system monitoring and maintenance, log rotation, or installing software packages, Bash scripts can execute these commands with minimal to no input from the user.

Basic Shell Commands

The terminal operates through a set of commands that the shell interprets. Bash, as the default shell in most Unix-based systems, processes these commands to perform a variety of tasks. Some of the most common commands you will use are:

  • cd: Changes the current directory. For example, cd /home/user navigates to the specified directory.
  • ls: Lists the files and directories within the current directory. Running ls -l provides detailed information about the contents.
  • cp: Copies files or directories. For example, cp file1.txt /backup/ copies a file to a new location.
  • mv: Moves or renames files and directories. The command mv file1.txt file2.txt renames the file, while mv file1.txt /backup/ moves it to a different directory.
  • cat: Concatenates and displays the content of a file. Running cat file.txt shows the entire file’s contents on the terminal.
  • echo: Displays a line of text or the value of a variable. For example, echo “Hello, World!” prints the text within the quotes to the terminal.

Hello World: Your First Bash Script

Create A Simple Bash Script

To write your first Bash script, you have to create a file and add a few simple commands. To do this, you need a text editor like nano, vim, or gedit. Open your terminal and create a new file called hello.sh. You can use the following command to do this:

nano hello.sh

Inside this file, we will write a short script that prints “Hello, World!” to the terminal. The script starts with a special line (known as Shebang), followed by the echo command to print text. Below is the content you should add to the file:

#!/bin/bash

echo “Hello, World!”

This script may look simple, but it teaches two foundational concepts: how to specify which shell should run the script and how to display output in the terminal.

What Is Shebang?

The first line of your script, #!/bin/bash, plays an important role in telling the system how to execute the script. This line, called the “Shebang,” starts with #! followed by the path to the Bash interpreter.

In this case, the path is /bin/bash, which is the default location of Bash on most Unix-like systems (Linux and macOS). When the system encounters this line, it knows that the rest of the file should be interpreted using Bash.

The Shebang is important because Unix systems often have multiple shells installed. Aside from Bash, users may work with shells like Zsh (Z Shell), Csh (C Shell), or Fish (Friendly Interactive Shell).

If the system doesn’t know which interpreter to use, it could misinterpret the commands and fail to execute them properly. By specifying #!/bin/bash at the beginning of the file, you are explicitly directing the system to use the Bash interpreter.

On most Linux distributions and macOS, Bash resides in /bin/bash. However, some systems may use a different path, such as /usr/bin/bash or /usr/local/bin/bash. To accommodate these variations, some scripts use #!/usr/bin/env bash, which searches for the Bash interpreter in the system’s environment. This makes the script more portable across different Unix-based platforms.

Grant Execution Permission

After creating your Bash script, it exists as a simple text file. Although the script contains valid commands, the system will not execute it until you exclusively grant the necessary permissions.

For a script to become executable, the system needs explicit instructions through the chmod command.

In the terminal, use the command chmod +x to modify the file’s permissions to make it executable. The +x option stands for “adding execution permission.” To apply this to your script, you would run the following command:

chmod +x hello.sh

Run The Script

After making your script executable, the next step is to run it in the terminal. To do this, use the command ./scriptname.sh. In this case, if you created a script called hello.sh, you would enter:

./hello.sh

The ./ part of this command tells the system to look for the script in the current directory. Unix-based systems often separate executable files into specific system directories like /bin or /usr/bin. If you don’t specify ./, the terminal may not find your script and assume it doesn’t exist, even though it is in the same folder you’re working in.

Running ./hello.sh executes the script by feeding it to the Bash interpreter, which processes the commands line by line. In this example, the echo command gets executed and the message “Hello, World!” appears on the screen.

Basic Concepts In Bash Scripting With Syntax

Variable

Variables in Bash allow you to store and manage dynamic data within your scripts. By defining variables, you can reuse values, modify them, and make your script more flexible. The syntax for declaring a variable in Bash is:

NAME=”John”

Here, the variable NAME holds the value “John.” Unlike many programming languages, Bash does not require data types when declaring variables. It treats everything as a string by default.

One key point to remember is that there must be no spaces between the variable name, the equal sign, and the value. If spaces are present, the script will not interpret the variable correctly.

In order to access the value of a variable, you need to use the $ symbol. For example, to print the value of NAME, you can use:

echo $NAME

This would output “John” to the terminal.

By using variables, you can easily change the behavior of a script without hard-coding values. For instance, instead of writing the same file path multiple times, you can assign the path to a variable and reference it throughout the script. Here’s another example. You can capture user input and store it in a variable, then use that input later in the script.

read -p “Enter your name: ” USERNAME

echo “Hello, $USERNAME!”

Here, the read command captures input and assigns it to the variable USERNAME.

Input

In Bash scripting, the read command handles input by capturing text entered by the user during script execution. This input can then be stored in a variable for later use within the script. The syntax for using read is straightforward:

read VARIABLE_NAME

Here, the user’s input will be stored in the variable VARIABLE_NAME. For example, consider the following script that prompts the user to enter their name:

#!/bin/bash

echo “Enter your name:”

read NAME

echo “Hello, $NAME!”

When executed, this script prompts the user for their name, stores the input in the NAME variable, and then greets the user by name.

The read command also accepts options like -p (which displays a prompt on the same line as the input request) or -s for silent input (useful when entering sensitive data like passwords). Here’s an example using the -p option:

#!/bin/bash

read -p “Enter your favorite color: ” COLOR

echo “Your favorite color is $COLOR.”

Output

The echo command primarily handles the output in Bash scripting. It prints text or variables to the terminal. The basic syntax for echo is:

echo “Your message here”

This command prints the text within the quotes. For example:

#!/bin/bash

echo “Hello, World!”

This script prints “Hello, World!” to the terminal. You can also use echo to display the values of variables.

#!/bin/bash

NAME=”John”

echo “Hello, $NAME!”

In addition to plain text, you can format the output of echo by including special characters such as newlines (\n) or tabs (\t). To enable these characters, use the -e option.

#!/bin/bash

echo -e “Hello,\nWelcome to Bash scripting!”

This command prints “Hello” on one line and “Welcome to Bash scripting!” on the next line.

You can also redirect the output to files in Bash using echo. For instance, you can write the result of a script to a file rather than displaying it on the terminal. This is achieved with the > operator:

echo “This will be written to a file” > output.txt

This command writes the text to the file output.txt. If the file doesn’t exist, it creates one (or overwrites it if it does). If you want to append the output instead of overwriting the file, use the >> operator.

echo “This will be appended” >> output.txt

Comments

No matter how big a developer you are, always add comments to your code. They make your code readable and maintainable. Although Bash scripts are often short and simple, adding comments helps clarify the purpose and function of different sections of the code.

In Bash, single-line comments begin with the # symbol. Everything following the # on that line will be ignored by the interpreter. Here is an example of a comment in a script:

# This script prints a greeting

echo “Hello, World!”

Conditional Statements (if-else)

Decision-making or conditional statements in Bash allow scripts to make decisions based on specific conditions. The if-else statement is very popular and you can execute different sets of commands depending on whether a condition is true or false.

The basic syntax for an if-else statement in Bash looks like this:

if [ condition ]; then

    # commands to execute if true

else

    # commands to execute if false

fi

Conditions often involve checking file existence, comparing strings, or evaluating numerical values. For example, the condition [ -f “/path/to/file” ] checks if a file exists at the specified path. If the file exists, the script can perform specific actions. Here’s the code for this example:

if [ -f “/path/to/file” ]; then

    echo “File exists.”

else

    echo “File does not exist.”

fi

You can extend these conditional checks to more complex scenarios. For instance, you might want to compare two strings or evaluate numeric conditions. Bash provides operators for these comparisons (-eq for numbers or == for strings).

Loops (For And While)

If you want to automate repetitive tasks by executing a block of code multiple times, loops are the way to go. The two main types of loops are: for and while.

The for loop syntax in Bash is:

for i in {1..5}; do

    echo “Number: $i”

done

This loop iterates from 1 to 5, printing “Number: $i” for each value of i.

The while loop is another way to perform repetitive tasks. The syntax for a while loop looks like this:

while [ condition ]; do

    # commands to execute while the condition is true

done

In a while loop, the commands inside the loop continue executing as long as the condition remains true. This type of loop is very useful when waiting for a specific system state, like waiting for a file to appear or a process to complete.

For example, a while loop could keep checking for a file’s existence:

while [ ! -f “/path/to/file” ]; do

    echo “Waiting for file…”

    sleep 10

done

echo “File found.”

This loop checks for the file every 10 seconds, printing “Waiting for file…” until the file appears. Once the file is detected, the script exits the loop and prints “File found.”

Functions

Basic Syntax Of Functions

You can group a set of commands into blocks and reuse them multiple times with the help of functions. By defining a function, you can call it anywhere in your script without rewriting the same code. The basic syntax for defining a function is:

function_name() {

    # Commands

}

To call the function, simply use its name. Here’s a simple example that defines and calls a function:

#!/bin/bash

greet() {

    echo “Hello, $1!”

}

greet “Alice”

In this example, the function greet prints a personalized greeting. The function takes one argument, $1, which represents the first argument passed to the function. When calling greet “Alice”, the script outputs “Hello, Alice!”

Functions can accept multiple arguments, each accessible by numbered variables such as $1, $2, and so on. Here’s a function that calculates the sum of two numbers:

#!/bin/bash

add_numbers() {

    SUM=$(($1 + $2))

    echo “The sum is: $SUM”

}

add_numbers 5 10

The function add_numbers takes two arguments, adds them, and prints the result. Calling add_numbers 5 10 will output “The sum is: 15.”

Functions For Repeated Tasks

Instead of duplicating the same code block multiple times, you define the logic once in a function and call it whenever needed. For example, suppose you are working on a script that needs to perform regular backups. Instead of writing the backup logic repeatedly, you can place it inside a function:

#!/bin/bash

backup_files() {

    cp /path/to/source/* /path/to/destination/

    echo “Backup completed.”

}

# Call the function at different points in the script

backup_files

Here, the backup_files function copies files from the source directory to the destination and prints a confirmation message. If you need to back up files multiple times in the script, simply call backup_files wherever necessary.

Additionally, functions in Bash can return values by using the return command or by outputting a value that can be captured by the caller. Here’s an example of a function returning the exit status of a command:

#!/bin/bash

check_file() {

    if [ -f “$1” ]; then

        return 0  # File exists

    else

        return 1  # File does not exist

    fi

}

check_file “/path/to/file”

if [ $? -eq 0 ]; then

    echo “File found.”

else

    echo “File not found.”

fi

This check_file function checks if a file exists and returns an appropriate exit code. The calling script captures this exit status using $? and reacts based on whether the file was found.

Practical Bash Script Example

Here is a Bash script that will perform a file backup. It will allow the user to customize options, such as choosing the directory to back up and setting a backup destination. Additionally, the script will also include error checking. Here’s a brief overview of the script:

  • Ask the user for the source directory and destination directory.
  • Check if both directories exist.
  • If the directories exist, it will back up the files from the source to the destination.
  • Output the status of each step to the user.
  • Include a loop to provide an option to back up additional directories.
  • Use functions to repeat tasks (checking the existence of directories and performing the backup).

#!/bin/bash

# A script to back up files from one directory to another

 

# Function to check if a directory exists

check_directory() {

    if [ -d “$1” ]; then

        return 0  # Directory exists

    else

        return 1  # Directory does not exist

    fi

}

 

# Function to perform the backup

backup_files() {

    cp -r “$1″/* “$2”

    echo “Backup completed from $1 to $2”

}

 

# Main script starts here

echo “Welcome to the Backup Script!”

 

# Loop to allow multiple backups

while true; do

    # Input: Ask for the source directory

    read -p “Enter the directory you want to back up: ” SOURCE_DIR

    # Input: Ask for the destination directory

    read -p “Enter the backup destination directory: ” DEST_DIR

 

    # Check if the source directory exists

    check_directory “$SOURCE_DIR”

    if [ $? -ne 0 ]; then

        echo “Source directory does not exist. Please try again.”

        continue  # Skip to the next loop iteration

    fi

    # Check if the destination directory exists

    check_directory “$DEST_DIR”

    if [ $? -ne 0 ]; then

        echo “Destination directory does not exist. Please try again.”

        continue  # Skip to the next loop iteration

    fi

    # Output: Inform the user about the backup process

    echo “Backing up files from $SOURCE_DIR to $DEST_DIR…”

    # Perform the backup using the function

    backup_files “$SOURCE_DIR” “$DEST_DIR”

            # Ask the user if they want to perform another backup

    read -p “Do you want to back up another directory? (yes/no): ” RESPONSE 

    # Conditional statement: Check the user’s response

    if [ “$RESPONSE” != “yes” ]; then

        echo “Exiting the backup script.”

        break  # Exit the loop

    fi

done

echo “Script finished. Goodbye!”

Leave a Reply

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