Comprehensive Introduction to Bash Scripting

2024/09/30 Linux, Bash Total 5527 words,approximately 16 mins.

Comprehensive Introduction to Bash Scripting

Bash (short for Bourne-Again SHell) is a powerful command-line shell and scripting language commonly used on Unix-like systems such as Linux and macOS. Bash scripts enable you to automate repetitive tasks, manage system operations, and create complex workflows in an efficient way.

Table of Contents

  1. What Is Bash?
  2. Creating and Running a Bash Script
  3. Variables and Command Substitution
  4. User Input and Command-Line Arguments
  5. Control Structures
  6. Functions
  7. Working with Files
  8. Useful Built-in Commands
  9. Error Handling and Debugging
  10. Practical Examples
  11. Best Practices
  12. Further Reading and Resources

What Is Bash?

Bash is both a command interpreter and a scripting language:

  • Command interpreter (shell): It lets you type and execute commands interactively in a terminal.
  • Scripting language: You can create files (scripts) containing a sequence of commands, which are then run automatically, saving time and reducing errors.

Creating and Running a Bash Script

1). Create a new file (e.g., myscript.sh) with any text editor (vi, nano, gedit, etc.). 2). Add the shebang line at the top of the file to specify the interpreter:

   #!/bin/bash

3). Write your script by adding commands you would normally run in the terminal:

#!/bin/bash
echo "Hello, world!"

4). Make the script executable by running:

#!/bin/bash
chmod +x myscript.sh

5). Execute the script:

./myscript.sh

or

bash myscript.sh

Variables and Command Substitution

In Bash, you can create and use variables to store information, such as strings, numbers, or the output of commands.

Creating Variables

#!/bin/bash
name="Alice"
number=42

echo "My name is $name and my favorite number is $number."

Command Substitution

Command substitution lets you assign the output of a command to a variable:

#!/bin/bash
current_date=$(date)
echo "Today's date is $current_date."

Alternatively, older syntax uses backticks:

current_date=`date`

User Input and Command-Line Arguments

Reading User Input with read

#!/bin/bash
echo "Please enter your name:"
read user_name
echo "Hello, $user_name!"

Command-Line Arguments

$1, $2, $3, etc. represent the arguments passed to the script:

#!/bin/bash
echo "The first argument is $1"
echo "The second argument is $2"

To handle many arguments, you can use $@ or $* to represent all arguments.

Control Structures

Control structures allow you to alter the flow of your Bash scripts.

If-Else Statement

#!/bin/bash
aa=3.14
bb=3.14
c=$(echo "$aa == $bb" | bc)  # compares numerical values

if [[ "$c" -eq 1 ]]; then
  echo "true"
else
  echo "false"
fi

String Comparison Example

#!/bin/bash
flag_0="DISLOCATION"

if [ "$flag_0" = "DISLOCATION" ]; then
  echo "equal 000"
else
  echo "not equal 000"
fi

Common Operators:

  • -eq, -ne, -gt, -ge, -lt, -le: numeric comparisons
  • -z, -n: check if a string is empty or not
  • =, !=: string equality or inequality

For Loops

#!/bin/bash
for ((i=1; i<=200; i=i+5))
do
  echo $i
  echo loop.$i.dump
done

Another form (iterating over a list):

#!/bin/bash
for fruit in apple banana cherry
do
  echo "I like $fruit"
done

While Loops

#!/bin/bash
count=1
while [ $count -le 5 ]
do
  echo "Count is: $count"
  ((count++))
done

Case Statements

#!/bin/bash
echo "Enter a number between 1 and 3:"
read number

case $number in
  1)
    echo "You chose one."
    ;;
  2)
    echo "You chose two."
    ;;
  3)
    echo "You chose three."
    ;;
  *)
    echo "Invalid choice!"
    ;;
esac

Functions

Functions allow you to group related commands for easier reuse and better structure:

#!/bin/bash

function greet {
  echo "Hello, $1!"
}

greet "Alice"
greet "Bob"
  • $1, $2, etc., in functions refer to the function’s arguments.
  • The return command can return an integer status code, and echo can be used to produce function output.

Working with Files

Check if a File Exists and Is Not Empty

#!/bin/bash
if [ -s pidfile ]; then
  echo "hi"
else
  echo "empty"
fi

Creating, Appending, and Reading Files

#!/bin/bash
# Creating or overwriting a file
echo "Hello" > myfile.txt

# Appending to a file
echo "World" >> myfile.txt

# Reading a file line by line
while IFS= read -r line
do
  echo "Line: $line"
done < myfile.txt

Useful Built-in Commands

  • echo: Prints arguments to standard output.
  • read: Reads a line of input from standard input.
  • cd: Changes the current directory.
  • pwd: Prints the current working directory.
  • ls, cp, mv, rm: Basic file and directory management commands.
  • test or [ ]: Evaluates conditional expressions (used in if statements).
  • exit: Exits the script with an optional status code (0 for success).

Error Handling and Debugging

set Options

  • set -e: Exit the script when any command fails.
  • set -u: Treat unset variables as errors.
  • set -o pipefail: Return exit code of the last command that failed in a pipeline. Include them near the top of your script:
    #!/bin/bash
    set -euo pipefail
    

Using trap

#!/bin/bash
trap 'echo "An error occurred. Exiting..."' ERR

some_command_that_might_fail
echo "This won't run if the above command fails."

Debug Mode

  • Verbose mode: bash -v myscript.sh
  • Debug mode: bash -x myscript.sh (prints each command with its expanded arguments)

Practical Examples

  1. Monitoring Disk Usage ``` #!/bin/bash threshold=80

current_usage=$(df -h / | tail -1 | awk ‘{print $5}’ | sed ‘s/%//’) if [ $current_usage -gt $threshold ]; then echo “Warning: Disk usage is above $threshold%!” else echo “Disk usage is under control at $current_usage%.” fi


2. Backup Script

#!/bin/bash source_dir=”/home/user/documents” backup_dir=”/home/user/backup” timestamp=$(date +%Y%m%d%H%M)

mkdir -p “$backup_dir” cp -r “$source_dir” “${backup_dir}/documents_${timestamp}”

echo “Backup of $source_dir completed at ${timestamp}.” ```

Best Practices

  1. Use Meaningful Names: Give variables and functions descriptive names (count, backup_files, greet_user).
  2. Comment Your Code: Explain why certain commands are used, especially if they’re not obvious.
  3. Validate Inputs: Check that arguments and user inputs are valid before using them.
  4. Quote Variables: Put variables in quotes (“$var”) to prevent globbing and word splitting issues.
  5. Prefer $() for Command Substitution: It’s more readable than backticks.
  6. Use set -euo pipefail: Helps catch errors early and makes your script more robust.
  7. Test Incrementally: Run sections of your script as you build it to catch errors before they spread.

Further Reading and Resources

Document information:

Search

    Table of Contents