Table of Contents#
- Prerequisites
- What is a Bash Script?
- Your First Bash Script: "Hello, World!"
- Variables in Bash
- User Input
- Control Structures: If-Else Statements
- Loops: For and While
- Error Handling
- Putting It All Together: A Practical Script
- Best Practices for Bash Scripting
- Troubleshooting Common Issues
- Conclusion
- References
Prerequisites#
Before diving in, ensure you have:
- A Unix-like operating system (Linux, macOS, or WSL on Windows).
- Basic familiarity with the terminal (e.g., navigating directories with
cd, listing files withls). - A text editor (e.g.,
nano,vim, VS Code, or Sublime Text). - Bash installed (check with
bash --version; most systems include it by default).
What is a Bash Script?#
A bash script is a text file containing a sequence of commands that the bash shell can execute. It allows you to automate tasks by combining multiple commands into a single file. Scripts are useful for:
- Automating backups, log rotation, or file cleanup.
- Running complex workflows (e.g., processing data, deploying code).
- Simplifying repetitive tasks (e.g., renaming files, checking system status).
Your First Bash Script: "Hello, World!"#
Let’s start with the classic "Hello, World!" example to learn the basics of script structure.
Step 1: Create the Script File#
Open your text editor and create a new file named hello_world.sh. The .sh extension is a convention to indicate a shell script (though not strictly required).
Step 2: Add the Shebang Line#
Every bash script should start with a shebang line, which tells the system which interpreter to use to run the script. For bash, this is:
#!/bin/bash#!is called a "shebang" or "hashbang."/bin/bashis the path to the bash interpreter (verify withwhich bash).
Step 3: Add Commands#
Below the shebang line, add the command to print "Hello, World!" using echo:
#!/bin/bash
# This is a comment (ignored by the shell)
echo "Hello, World!"- Comments start with
#and help explain the script’s purpose.
Step 4: Make the Script Executable#
By default, the script is just a text file. To run it, you need to make it executable with chmod:
chmod +x hello_world.shchmod +xgrants "execute" permission to the file.
Step 5: Run the Script#
Execute the script using ./ (to specify the current directory):
./hello_world.shOutput:
Hello, World!
Congratulations! You’ve written and run your first bash script.
Variables in Bash#
Variables store data for reuse in scripts. They help make scripts dynamic and readable.
Defining Variables#
Variables are defined with variable_name=value (no spaces around =):
name="Alice"
age=30Accessing Variables#
Use $variable_name to access a variable’s value:
#!/bin/bash
name="Alice"
echo "Hello, $name!" # Output: Hello, Alice!Command Substitution#
Capture the output of a command into a variable using $(command):
#!/bin/bash
current_date=$(date +"%Y-%m-%d") # Get current date in YYYY-MM-DD format
echo "Today is $current_date" # Output: Today is 2024-05-20 (example)User Input#
Use the read command to get input from the user during script execution.
Basic Input#
#!/bin/bash
echo "What is your name?"
read name # Stores user input in the 'name' variable
echo "Hello, $name!"Prompt with read -p#
Use -p to display a prompt directly:
#!/bin/bash
read -p "Enter your name: " name
echo "Welcome, $name!"Output:
Enter your name: Bob
Welcome, Bob!
Control Structures: If-Else Statements#
If-else statements let you run commands conditionally.
Syntax#
if [ condition ]; then
# Commands to run if condition is true
elif [ another_condition ]; then
# Commands if first condition is false, second is true
else
# Commands if all conditions are false
fi # Closes the if statement- Note: Spaces around
[and]are required (they’re part of thetestcommand).
Example: Check if a Number is Positive/Negative/Zero#
#!/bin/bash
read -p "Enter a number: " num
if [ $num -gt 0 ]; then # -gt = greater than
echo "$num is positive"
elif [ $num -lt 0 ]; then # -lt = less than
echo "$num is negative"
else
echo "$num is zero"
fiOutput:
Enter a number: -5
-5 is negative
Common Conditions#
| Operator | Meaning | Example |
|---|---|---|
-eq | Equal to | [ $a -eq $b ] |
-ne | Not equal to | [ $a -ne $b ] |
-gt | Greater than | [ $a -gt $b ] |
-lt | Less than | [ $a -lt $b ] |
-ge | Greater than or equal to | [ $a -ge $b ] |
-le | Less than or equal to | [ $a -le $b ] |
-f | File exists and is a regular file | [ -f "file.txt" ] |
-d | Directory exists | [ -d "my_dir" ] |
Loops: For and While#
Loops repeat commands multiple times.
For Loops: Iterate Over Items#
Syntax: for item in list; do ... done#
#!/bin/bash
# Loop through numbers 1-5
for i in {1..5}; do
echo "Number: $i"
doneOutput:
Number: 1
Number: 2
Number: 3
Number: 4
Number: 5
Loop Through Files in a Directory#
#!/bin/bash
# List all .txt files in the current directory
echo "Text files in current directory:"
for file in *.txt; do
echo "- $file"
doneWhile Loops: Repeat Until a Condition Fails#
Syntax: while [ condition ]; do ... done#
#!/bin/bash
count=1
while [ $count -le 5 ]; do
echo "Count: $count"
count=$((count + 1)) # Increment count
doneOutput:
Count: 1
Count: 2
Count: 3
Count: 4
Count: 5
Error Handling#
Prevent scripts from failing silently with error-handling techniques.
Exit on Error with set -e#
Add set -e at the top of your script to exit immediately if any command fails:
#!/bin/bash
set -e # Exit on error
echo "This command succeeds"
ls non_existent_file.txt # This fails, so the script exits here
echo "This line will NOT run"Check Exit Codes#
Every command returns an exit code (0 = success, non-zero = failure). Access it with $?:
#!/bin/bash
ls "existing_file.txt"
echo "Exit code: $?" # Output: 0 (success)
ls "non_existent_file.txt"
echo "Exit code: $?" # Output: 2 (failure)Putting It All Together: A Practical Script#
Let’s combine variables, user input, if statements, loops, and error handling into a script that analyzes a directory.
Script: directory_analyzer.sh#
#!/bin/bash
set -euo pipefail # Exit on error, unset variable, or pipeline failure
# Greet the user and get their name
read -p "Hello! What's your name? " username
echo "Nice to meet you, $username! Let's analyze a directory."
# Get directory path from the user
read -p "Enter the directory path to analyze: " dir_path
# Check if the directory exists
if [ ! -d "$dir_path" ]; then
echo "Error: Directory '$dir_path' does not exist."
exit 1 # Exit with code 1 (failure)
fi
# List files in the directory
echo -e "\nFiles in $dir_path:"
ls -l "$dir_path"
# Count total files (excluding directories)
file_count=$(find "$dir_path" -maxdepth 1 -type f | wc -l)
echo -e "\nTotal files in directory: $file_count"
# Loop through files and print names
echo -e "\nPrinting filenames:"
for file in "$dir_path"/*; do
if [ -f "$file" ]; then # Only process regular files
echo "- $(basename "$file")" # Get filename without path
fi
done
echo -e "\nAnalysis complete. Goodbye, $username!"How It Works:#
- Shebang & Error Handling:
#!/bin/bashandset -euo pipefailensure robustness. - User Input:
read -pgets the username and directory path. - Condition Check:
[ ! -d "$dir_path" ]verifies the directory exists. - Command Substitution:
$(find ... | wc -l)counts files. - Loop: Iterates over files and prints names with
basename.
Run the Script:#
chmod +x directory_analyzer.sh
./directory_analyzer.shBest Practices for Bash Scripting#
- Use Comments: Explain complex logic with
#. - Meaningful Variables: Use names like
user_countinstead ofx. - Quote Variables:
"$variable"prevents errors with spaces in filenames. - Test Scripts: Run incrementally and test edge cases (e.g., empty directories).
- Set Permissions: Always
chmod +xto make scripts executable. - Shebang Line: Start with
#!/bin/bash(not#!/bin/shunless POSIX compliance is needed). - Avoid Spaces in Filenames: They complicate scripting (use underscores instead).
Troubleshooting Common Issues#
- "Permission denied": Run
chmod +x script.shto make it executable. - "Command not found": Ensure the script’s path is correct (use
./script.shfor the current directory). - Syntax Errors: Check for missing
fi(if) ordone(loops), or spaces around[ ]. - Variables Not Working: Ensure no spaces around
=(e.g.,name="Bob"notname = "Bob").
Conclusion#
You’ve learned the fundamentals of bash scripting: creating scripts, variables, user input, control structures, loops, error handling, and best practices. Start small (e.g., automate file backups) and gradually build more complex scripts. The more you practice, the more proficient you’ll become at leveraging bash to simplify your workflow.
References#
- GNU Bash Manual
- Bash Beginners Guide (TLDP)
- ShellCheck (Linter for Bash) – Debug scripts for errors.
- Bash Hackers Wiki – Advanced tips and tricks.