Bash Scripting Basics

Learn to write Bash scripts with conditionals, loops, functions, and user input. Master the fundamentals of shell script development.

📖 6 min read📅 2026-02-10Scripting

Your First Script

#!/bin/bash
# My first Bash script
 
echo "Hello, World!"
echo "Today is $(date)"
echo "You are logged in as: $USER"
echo "Current directory: $PWD"

Running the Script

# Method 1: Make executable
chmod +x script.sh
./script.sh
 
# Method 2: Run with bash
bash script.sh
 
# Method 3: Source (runs in current shell)
source script.sh
. script.sh

The Shebang Line

#!/bin/bash          # Use Bash
#!/usr/bin/env bash  # Find Bash in PATH (more portable)
#!/bin/sh            # Use POSIX shell (more compatible)

Conditionals (if/elif/else)

Test Syntax

# Using [ ] (test command)
if [ "$name" = "Alice" ]; then
    echo "Hello Alice!"
fi
 
# Using [[ ]] (Bash extended test - preferred)
if [[ "$name" == "Alice" ]]; then
    echo "Hello Alice!"
fi
 
# if/elif/else
age=25
if [[ $age -lt 13 ]]; then
    echo "Child"
elif [[ $age -lt 18 ]]; then
    echo "Teenager"
elif [[ $age -lt 65 ]]; then
    echo "Adult"
else
    echo "Senior"
fi

String Comparisons

[[ "$a" == "$b" ]]     # Equal
[[ "$a" != "$b" ]]     # Not equal
[[ "$a" < "$b" ]]      # Less than (alphabetical)
[[ "$a" > "$b" ]]      # Greater than
[[ -z "$a" ]]          # Empty string
[[ -n "$a" ]]          # Non-empty string
[[ "$a" == *pattern* ]] # Wildcard match
[[ "$a" =~ regex ]]    # Regex match

Numeric Comparisons

[[ $a -eq $b ]]     # Equal
[[ $a -ne $b ]]     # Not equal
[[ $a -lt $b ]]     # Less than
[[ $a -le $b ]]     # Less or equal
[[ $a -gt $b ]]     # Greater than
[[ $a -ge $b ]]     # Greater or equal

File Tests

[[ -e file ]]       # File exists
[[ -f file ]]       # Is a regular file
[[ -d dir ]]        # Is a directory
[[ -r file ]]       # Is readable
[[ -w file ]]       # Is writable
[[ -x file ]]       # Is executable
[[ -s file ]]       # Is non-empty
[[ -L file ]]       # Is a symlink
[[ file1 -nt file2 ]]  # file1 is newer
[[ file1 -ot file2 ]]  # file1 is older

Logical Operators

# AND
if [[ $age -gt 18 && $has_license == "yes" ]]; then
    echo "Can drive"
fi
 
# OR
if [[ $day == "Saturday" || $day == "Sunday" ]]; then
    echo "Weekend!"
fi
 
# NOT
if [[ ! -f "config.txt" ]]; then
    echo "Config file missing!"
fi

Case Statement

read -p "Enter a fruit: " fruit
 
case $fruit in
    apple|Apple)
        echo "🍎 Red fruit"
        ;;
    banana|Banana)
        echo "🍌 Yellow fruit"
        ;;
    grape|Grape)
        echo "🍇 Purple fruit"
        ;;
    *)
        echo "Unknown fruit: $fruit"
        ;;
esac

Loops

for Loop

# List iteration
for name in Alice Bob Charlie; do
    echo "Hello, $name"
done
 
# Range
for i in {1..10}; do
    echo "Number: $i"
done
 
# Range with step
for i in {0..20..2}; do
    echo "Even: $i"
done
 
# C-style for loop
for ((i = 0; i < 10; i++)); do
    echo "Index: $i"
done
 
# Iterate over files
for file in *.txt; do
    echo "Processing: $file"
    wc -l "$file"
done
 
# Iterate over command output
for user in $(cut -d: -f1 /etc/passwd); do
    echo "User: $user"
done
 
# Iterate over array
servers=("web01" "web02" "db01")
for server in "${servers[@]}"; do
    echo "Checking $server..."
done

while Loop

# Basic while
count=1
while [[ $count -le 5 ]]; do
    echo "Count: $count"
    ((count++))
done
 
# Read file line by line
while IFS= read -r line; do
    echo "Line: $line"
done < input.txt
 
# Infinite loop with break
while true; do
    read -p "Enter 'quit' to exit: " input
    if [[ "$input" == "quit" ]]; then
        break
    fi
    echo "You entered: $input"
done
 
# Read from command output
while read -r pid name cpu; do
    echo "$name (PID: $pid) using $cpu% CPU"
done < <(ps aux --sort=-%cpu | awk 'NR>1{print $2, $11, $3}' | head -5)

until Loop

# Loop until condition is true
count=1
until [[ $count -gt 5 ]]; do
    echo "Count: $count"
    ((count++))
done

Functions

# Basic function
greet() {
    echo "Hello, $1!"
}
greet "Alice"    # "Hello, Alice!"
 
# Function with return value
is_even() {
    if (( $1 % 2 == 0 )); then
        return 0    # success/true
    else
        return 1    # failure/false
    fi
}
 
if is_even 42; then
    echo "42 is even"
fi
 
# Function with output (preferred for returning data)
get_greeting() {
    local name="${1:-World}"
    echo "Hello, $name!"
}
 
message=$(get_greeting "Alice")
echo "$message"
 
# Local variables
my_function() {
    local local_var="I'm local"
    global_var="I'm global"
    echo "$local_var"
}
 
my_function
echo "$global_var"    # Works
# echo "$local_var"   # Empty (local to function)

User Input

# Basic read
read -p "Enter your name: " name
echo "Hello, $name!"
 
# Silent input (passwords)
read -sp "Enter password: " password
echo
 
# With timeout
read -t 10 -p "Quick! Enter a number: " num
 
# Default value
read -p "Enter color [blue]: " color
color=${color:-blue}
 
# Read into array
read -a colors -p "Enter colors (space-separated): "
echo "First color: ${colors[0]}"

Practical Script Example

#!/bin/bash
# System Health Check Script
 
set -euo pipefail
 
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
 
check_disk() {
    echo -e "\n${YELLOW}=== Disk Usage ===${NC}"
    df -h / | tail -1 | awk '{
        usage = int($5)
        if (usage > 90) color = "31"      # Red
        else if (usage > 70) color = "33"  # Yellow
        else color = "32"                   # Green
        printf "Root: \033[%sm%s used\033[0m (%s free)\n", color, $5, $4
    }'
}
 
check_memory() {
    echo -e "\n${YELLOW}=== Memory Usage ===${NC}"
    free -h | awk '/^Mem:/ {
        printf "Total: %s | Used: %s | Free: %s\n", $2, $3, $4
    }'
}
 
check_cpu() {
    echo -e "\n${YELLOW}=== CPU Load ===${NC}"
    uptime | awk -F'load average:' '{print "Load Average:" $2}'
}
 
check_services() {
    echo -e "\n${YELLOW}=== Key Services ===${NC}"
    for service in sshd nginx mysql; do
        if systemctl is-active "$service" &>/dev/null; then
            echo -e "  $service: ${GREEN}RUNNING${NC}"
        else
            echo -e "  $service: ${RED}STOPPED${NC}"
        fi
    done
}
 
# Main
echo "============================="
echo "  System Health Check"
echo "  $(date)"
echo "============================="
 
check_disk
check_memory
check_cpu
check_services
 
echo -e "\n${GREEN}Health check complete!${NC}"

Exercises

  1. Write a script that takes a directory path and lists all files with their sizes
  2. Create a multiplication table script using nested for loops
  3. Write a function library with string utility functions (trim, uppercase, lowercase, reverse)
  4. Build an interactive menu system for common system admin tasks
  5. Create a script that reads a CSV file and generates a formatted report

Next: Text Processing with grep, sed, awk — master text manipulation!