Bash Shell Scripts â Complete Guide to Writing Reusable Automation
In this tutorial, you'll learn about Bash Shell Scripts. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
Bash scripts turn repetitive command-line tasks into reusable programs â combining variables, conditionals, loops, and functions in a text file that runs on any Unix system without extra software.
What You'll Learn
- Write your first Bash script with variables and command substitution
- Use conditionals (
if,elif,else) to make decisions - Automate repetitive work with
for,while, anduntilloops - Organize logic into reusable functions with
localvariables - Handle errors with exit codes and
set -e - Schedule scripts with
cron
Why Shell Scripts Matter
Every repetitive task you do in the terminal â renaming files, checking disk space, backing up data â can be automated with a script. Durga Antivirus Pro uses Bash scripts to rotate scan logs, update virus definitions at 3 AM daily, and quarantine infected files automatically. DodaZIP scripts batch-compress uploads, verify archive integrity, and email reports. A single well-written script replaces hours of manual work every week.
Learning Path
flowchart LR A[Bash Basics] --> B[Pipes & Redirection] B --> C[Shell Scripts
You are here] C --> D[Permissions & Users] D --> E[System Monitoring]
Prerequisites: Familiarity with Bash (navigating files, running commands) and Linux like nano or vim. You should understand Bash.
What Is a Shell Script?
Think of a Shell Script as a recipe. A recipe lists ingredients (variables) and steps (commands). You write it once, and anyone with the same kitchen (a Unix system) can follow it to get the same result.
A script is just a text file with:
- A shebang line (
#!/bin/bash) that says "use Bash to interpret this" - Commands that run in order
- Execute permission so the system treats it as a program
Your First Script
#!/bin/bash
# My first script â says hello and shows the date
echo "Hello, World!"
echo "Today is: $(date)"
To run it:
# Make it executable (like turning on the "run" switch)
chmod +x hello.sh
# Execute it
./hello.sh
# Hello, World!
# Today is: Sat Jun 6 12:00:00 UTC 2026
Line by line:
#!/bin/bashâ the shebang. It tells the kernel: "this script needs Bash." Without it, the system tries to run the file with/bin/sh, which may not support all Bash features.#â comments. Anything after#is ignored. Use comments to explain why you're doing something.echoâ prints text to the terminal.$(date)â command substitution. Runs thedatecommand and inserts its output. Think of it like: run this first, then use the result.
Variables â Labeled Boxes
A variable is a labeled box that holds a value. You put something in it and refer to it by the label.
#!/bin/bash
name="Alice" # Put "Alice" into the box labeled "name"
greeting="Hello" # Put "Hello" into the box labeled "greeting"
echo "$greeting, $name!" # Take things out of the boxes
# Hello, Alice!
Key rules:
- No spaces around
=âname = "Alice"is wrong (Bash thinksnameis a command to run) - Use
$to get the value out â$namemeans "the contents of the box named name" - Quote variables with spaces â
"$name"keeps the value intact
Command Substitution
# Run a command and store its output
files=$(ls -la)
echo "$files"
# Older syntax (same thing)
files=`ls -la`
Arithmetic
count=$((5 + 3))
echo "Count: $count"
# Count: 8
# Increment
count=$((count + 1))
echo "Now: $count"
# Now: 9
Special Variables
Bash automatically sets these variables:
| Variable | Holds | Example |
|---|---|---|
$0 |
Script name | ./backup.sh |
$1, $2, ... |
Positional arguments | ./script.sh hello â $1 = hello |
$# |
Number of arguments | 2 if you passed two args |
$@ |
All arguments as separate words | "arg1" "arg2" "arg3" |
$? |
Exit code of last command | 0 = success, 1 = error |
$$ |
Current script PID | 12345 |
$HOME |
User's home directory | /home/you |
$USER |
Current username | you |
Conditionals â Making Decisions
Conditionals let your script make choices. Think of them like a fork in the road.
#!/bin/bash
# If the first argument is "hello", greet warmly
if [ "$1" = "hello" ]; then
echo "Hi there!"
elif [ "$1" = "bye" ]; then
echo "See you!"
else
echo "Say hello or bye"
fi
Breaking down the if syntax:
if [ condition ]; then
commands
fi
The spaces inside [ ] are mandatory. [ "$1" = "hello" ] works; ["$1"="hello"] fails. Think of [ as a command itself â it needs spaces around its arguments.
File Tests
if [ -f "/etc/passwd" ]; then
echo "passwd file exists"
fi
if [ -d "/home/you/projects" ]; then
echo "Projects directory exists"
fi
Numeric Comparison
count=15
if [ "$count" -gt 10 ]; then
echo "More than 10"
fi
Notice: -gt (greater than), not >. Bash uses letters for numeric comparison because > is used for redirection.
Logical Operators
if [ "$age" -gt 18 ] && [ "$age" -lt 65 ]; then
echo "Working age"
fi
Loops â Doing Things Repeatedly
Loops are like an assembly line: the same operation repeats on each item.
For Loop
# Loop over a list of values
for fruit in apple banana cherry; do
echo "I like $fruit"
done
# I like apple
# I like banana
# I like cherry
# Loop over files matching a pattern
for file in *.txt; do
echo "Processing $file"
wc -l "$file"
done
# C-style loop with a counter
for ((i=0; i<5; i++)); do
echo "Iteration $i"
done
While Loop
# Loop while a condition is true
count=1
while [ "$count" -le 5 ]; do
echo "Count: $count"
count=$((count + 1))
done
Reading a File Line by Line
while IFS= read -r line; do
echo "Line: $line"
done < input.txt
IFS= prevents splitting on spaces. -r prevents backslash interpretation. done < input.txt feeds the file as input.
Functions â Organizing Logic
Functions are like sub-recipes within your main recipe. They let you reuse logic without copying and pasting.
#!/bin/bash
# Define a function
greet() {
local name="$1" # $1 is the first argument passed to the function
echo "Hello, $name!"
}
# Call it
greet "Alice"
greet "Bob"
Why local matters: Without local, variables inside functions are global. Modifying a global variable inside a function can cause bugs that are hard to track.
# Function with a return code
is_even() {
local num=$1
return $((num % 2))
}
if is_even 4; then
echo "Even"
else
echo "Odd"
fi
Exit Codes â Success or Failure
Every command returns an exit code: 0 means success, anything else means failure.
#!/bin/bash
# Check if a config file exists
if [ ! -f "config.yaml" ]; then
echo "Error: config not found"
exit 1
fi
echo "Config found, proceeding..."
The exit 1 stops the script immediately and tells the caller it failed. Think of it like: "Abort mission â missing equipment."
Strict Mode â Write Safer Scripts
Always start your scripts with these three lines:
#!/bin/bash
set -e # Exit immediately if any command fails
set -u # Treat unset variables as an error
set -o pipefail # Make pipes fail if any part fails
set -e: Without this, your script cheerfully continues afterrm nonexistent-filefails, potentially causing worse damage.set -u: Catches typos.echo "$nme"(typo) exits immediately instead of printing an empty line.set -o pipefail: Without it,false | echo "hi"exits with code 0 (success). With it, the pipe fails if any step fails.
Cron â Automate on a Schedule
Cron is like an alarm clock for your scripts. It runs them at specified times automatically.
# Edit your cron job schedule
crontab -e
# Syntax: minute hour day month weekday command
# âââââââââ minute (0-59)
# â âââââââ hour (0-23)
# â â âââââ day of month (1-31)
# â â â âââ month (1-12)
# â â â â â weekday (0-7, 0=Sunday)
# â â â â â
# * * * * * command
# Run backup script daily at 3 AM
0 3 * * * /home/you/backup.sh
# Run health check every hour
0 * * * * /home/you/check-status.sh
# View scheduled jobs
crontab -l
Common Mistakes
1. Spaces around = in assignments
name = "Alice" # WRONG â Bash thinks "name" is a command with args
name="Alice" # CORRECT
2. Forgetting $ on variables
count=5
echo count # Prints "count", not 5
echo $count # CORRECT
3. Not quoting variables
file="My Document.txt"
cat $file # Tries cat "My" and "Document.txt" â fails
cat "$file" # CORRECT
4. Using [ instead of [[
[[ ]] has pattern matching, regex, and is safer with empty variables. Always prefer [[ ]] in Bash scripts.
5. Not using local in functions
Variables are global by default. Functions silently modify global state. Always declare function variables with local.
6. Forgetting set -e at the top
Without it, your script continues after errors, potentially corrupting data or causing cascading failures.
Practice Questions
What does
#!/bin/bashdo? It's the shebang â tells the system to use/bin/bashas the Interpreter for the script.What is the difference between
$@and$*?$@treats each argument as a separate word (preserves quoting).$*joins all arguments into one string. Always use$@.How do you debug a Bash script? Run
bash -x script.shto see every command executed, or addset -xinside the script to print commands as they run.What does
set -edo? Makes the script exit immediately if any command fails (returns non-zero exit code).How do you read a file line by line in a script?
while IFS= read -r line; do echo "$line"; done < file.txt
Challenge: Write a script that takes a directory path as an argument, checks if it exists, counts how many files are in it (recursively), and reports the total size in human-readable format. If the directory doesn't exist, exit with code 1 and an error message.
FAQ
Try It Yourself
Create a simple backup script to practice:
#!/bin/bash
set -e
# Backup script â copies files and creates a timestamped archive
SOURCE="$HOME/Documents"
DEST="$HOME/backups"
DATE=$(date +%Y%m%d_%H%M%S)
FILENAME="backup-$DATE.tar.gz"
echo "Starting backup of $SOURCE..."
# Create destination if it doesn't exist
mkdir -p "$DEST"
# Create the archive
tar czf "$DEST/$FILENAME" "$SOURCE"
echo "Backup created: $DEST/$FILENAME"
echo "Size: $(du -sh "$DEST/$FILENAME" | cut -f1)"
Save as backup.sh, run chmod +x backup.sh, then ./backup.sh. Try breaking it (remove the set -e and see what happens when a command fails).
What's Next
| Tutorial | What You'll Learn |
|---|---|
| Permissions & Users | Manage read/write/execute permissions for scripts |
| System Monitoring | Monitor CPU, memory, disk with scripts |
| Linux Cron Jobs | Advanced scheduling and automation patterns |
| Python Automation | Compare Bash scripts with Python for complex tasks |
What's Next
Congratulations on completing this Bash Scripts tutorial! Here's where to go from here:
- Practice daily â Consistency is more important than long study sessions
- Build a project â Apply what you learned by building something real
- Explore related topics â Check out other tutorials in the same category
- Join the community â Discuss with other learners and share your progress
Remember: every expert was once a beginner. Keep coding!
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro