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
- What Is Bash?
- Creating and Running a Bash Script
- Variables and Command Substitution
- User Input and Command-Line Arguments
- Control Structures
- Functions
- Working with Files
- Useful Built-in Commands
- Error Handling and Debugging
- Practical Examples
- Best Practices
- 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
- 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
- Use Meaningful Names: Give variables and functions descriptive names (count, backup_files, greet_user).
- Comment Your Code: Explain why certain commands are used, especially if they’re not obvious.
- Validate Inputs: Check that arguments and user inputs are valid before using them.
- Quote Variables: Put variables in quotes (“$var”) to prevent globbing and word splitting issues.
- Prefer $() for Command Substitution: It’s more readable than backticks.
- Use set -euo pipefail: Helps catch errors early and makes your script more robust.
- Test Incrementally: Run sections of your script as you build it to catch errors before they spread.
Further Reading and Resources
- Official Bash Manual: https://www.gnu.org/software/bash/manual/
- Advanced Bash-Scripting Guide: https://tldp.org/LDP/abs/html/
- Linux Command Tutorials: https://linuxcommand.org/
Document information:
- Author:Lei Zhang
- Link:https://leiapple.github.io/2024/09/30/bash-start/
- Copyright:Creative Commons licenses( cc3.0 )