Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Control Structures

Hash shell supports POSIX-compatible control structures for flow control.

If/Then/Else

Syntax

if command; then
    commands
fi

if command; then
    commands
else
    commands
fi

if command; then
    commands
elif command; then
    commands
else
    commands
fi

Examples

# Simple if
if [ -f "/etc/passwd" ]; then
    echo "passwd file exists"
fi

# If/else
if [ "$USER" = "root" ]; then
    echo "Running as root"
else
    echo "Running as $USER"
fi

# If/elif/else
if [ $count -lt 0 ]; then
    echo "Negative"
elif [ $count -eq 0 ]; then
    echo "Zero"
else
    echo "Positive"
fi

Any Command as Condition

if grep -q "pattern" file.txt; then
    echo "Found"
fi

if command -v git > /dev/null; then
    echo "Git installed"
fi

For Loops

Syntax

for var in list; do
    commands
done

Examples

# List of words
for name in Alice Bob Charlie; do
    echo "Hello, $name"
done

# Files
for file in *.txt; do
    echo "Processing: $file"
done

# Arguments
for arg in "$@"; do
    echo "Argument: $arg"
done

# Numbers
for i in $(seq 1 5); do
    echo "Number: $i"
done

While Loops

Syntax

while command; do
    commands
done

Examples

count=0
while [ $count -lt 5 ]; do
    echo "Count: $count"
    count=$((count + 1))
done

# Read lines
while read line; do
    echo "Line: $line"
done < file.txt

# Infinite loop
while true; do
    echo "Press Ctrl+C"
    sleep 1
done

Until Loops

Syntax

until command; do
    commands
done

Example

count=0
until [ $count -ge 5 ]; do
    echo "Count: $count"
    count=$((count + 1))
done

Case Statements

Syntax

case word in
    pattern1)
        commands
        ;;
    pattern2|pattern3)
        commands
        ;;
    *)
        default
        ;;
esac

Examples

case "$1" in
    start)
        echo "Starting..."
        ;;
    stop)
        echo "Stopping..."
        ;;
    *)
        echo "Usage: $0 {start|stop}"
        ;;
esac

# Pattern matching
case "$filename" in
    *.txt)
        echo "Text file"
        ;;
    *.sh)
        echo "Shell script"
        ;;
    *)
        echo "Unknown"
        ;;
esac

Nesting

for dir in /home/*; do
    if [ -d "$dir" ]; then
        for file in "$dir"/*.txt; do
            if [ -f "$file" ]; then
                echo "Found: $file"
            fi
        done
    fi
done

Common Mistakes

Missing Spaces

# Wrong
if [-f "$file"]; then

# Correct
if [ -f "$file" ]; then

Unquoted Variables

# Wrong
for file in $files; do

# Correct
for file in "$files"; do

= vs -eq

# String comparison
if [ "$str" = "value" ]; then

# Numeric comparison
if [ $num -eq 5 ]; then