Bash Shell Scripts — Complete Guide to Writing Reusable Automation
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<br/>You are here]
C --> D[Permissions & Users]
D --> E[System Monitoring]
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 2026Line 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: 9Special 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"
fiBreaking down the if syntax:
if [ condition ]; then
commands
fiThe 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"
fiNumeric Comparison
count=15
if [ "$count" -gt 10 ]; then
echo "More than 10"
fiNotice: -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"
fiLoops — 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"
doneWhile Loop
# Loop while a condition is true
count=1
while [ "$count" -le 5 ]; do
echo "Count: $count"
count=$((count + 1))
doneReading a File Line by Line
while IFS= read -r line; do
echo "Line: $line"
done < input.txtIFS= 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"
fiExit 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 failsset -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 -lCommon Mistakes
1. Spaces around = in assignments
name = "Alice" # WRONG — Bash thinks "name" is a command with args
name="Alice" # CORRECT2. Forgetting $ on variables
count=5
echo count # Prints "count", not 5
echo $count # CORRECT3. Not quoting variables
file="My Document.txt"
cat $file # Tries cat "My" and "Document.txt" — fails
cat "$file" # CORRECT4. 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