Shell Script Tutorial for Beginners - Bash Variables, If, and Loops

Shell Script Tutorial for Beginners - Bash Variables, If, and Loops

Shell scripting is a powerful tool for automating tasks in Linux systems. In this basics edition, you'll learn Bash script syntax from variables and conditionals to loops, with practical examples throughout.

What You'll Learn

  • How to create and run your first Bash script with the shebang line and execute permission
  • How to define variables, use special variables, and accept user input with read
  • How to write if/elif/else conditionals and case statements with correct syntax
  • How for, while, and until loops work, including file processing and loop control
  • The six most common beginner mistakes and how to avoid them

Your First Shell Script

Conclusion: #!/bin/bash, chmod +x, ./script.sh — three steps that start every Bash script.

Basic Structure

#!/bin/bash
# This is a comment

echo "Hello, Shell Script!"
echo "Current date/time: $(date)"
echo "Username: $USER"

Creating and Running Scripts

Step 1: Create File

$ nano hello.sh

Enter the above code and save.

Step 2: Add Execute Permission

$ chmod +x hello.sh

Step 3: Run Script

$ ./hello.sh
Hello, Shell Script!
Current date/time: Mon Jan 11 14:30:00 JST 2025
Username: user

About Shebang

#!/bin/bash is called a shebang and specifies the interpreter to execute this file.

  • #!/bin/bash — Use Bash
  • #!/bin/sh — Use POSIX shell
  • #!/usr/bin/env bash — Auto-detect from environment

Variables and Input

Conclusion: No spaces around =; quote all uses; use $() for substitution; read -p for input.

Variable Basics

#!/bin/bash

# Define variables (no spaces around =)
name="Linux User"
age=25
today=$(date +%Y-%m-%d)

# Use variables
echo "Name: $name"
echo "Age: ${age} years old"
echo "Today's date: $today"

Calculation Example

#!/bin/bash

num1=10
num2=3

sum=$((num1 + num2))
diff=$((num1 - num2))
product=$((num1 * num2))
quotient=$((num1 / num2))

echo "Addition: $num1 + $num2 = $sum"
echo "Subtraction: $num1 - $num2 = $diff"
echo "Multiplication: $num1 × $num2 = $product"
echo "Division: $num1 ÷ $num2 = $quotient"

Special Variables

Variable Description Example
$0 Script name ./script.sh
$1, $2, ... Command line arguments 1st arg, 2nd arg
$# Number of arguments 3 for 3 arguments
$@ All arguments "arg1" "arg2" "arg3"
$? Exit status of last command 0 for success, non-0 for failure
$$ Current process ID 12345
$USER Current username user
$HOME Home directory /home/user
$PWD Current directory /home/user/scripts

User Input

Basic Input

#!/bin/bash

echo "Please enter your name:"
read name
echo "Hello, ${name}!"

Input with Prompt

#!/bin/bash

read -p "Enter your age: " age
read -s -p "Enter password: " password
echo
echo "Age: $age"
echo "Password entered silently"

Multiple Values at Once

#!/bin/bash

echo "Enter name and age (space-separated):"
read name age
echo "Name: $name, Age: $age"

Conditionals

Conclusion: Spaces inside [ ] required; quote string variables; use -eq/-gt/-lt for numbers.

if Statement

Basic if Statement

#!/bin/bash

read -p "Enter a number: " num

if [ "$num" -gt 0 ]; then
    echo "$num is positive"
elif [ "$num" -lt 0 ]; then
    echo "$num is negative"
else
    echo "$num is zero"
fi

File Existence Check

#!/bin/bash

filename="test.txt"

if [ -f "$filename" ]; then
    echo "$filename exists"
    echo "File size: $(wc -c < "$filename") bytes"
else
    echo "$filename does not exist"
    echo "Creating file..."
    touch "$filename"
fi

Conditional Operators

Numeric Comparison

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

String Comparison

Operator Meaning Example
= Equal [ "$a" = "$b" ]
!= Not equal [ "$a" != "$b" ]
-z Empty string [ -z "$str" ]
-n Not empty [ -n "$str" ]

File Tests

Operator Meaning Example
-f Regular file [ -f file.txt ]
-d Directory [ -d /home ]
-e Exists [ -e path ]
-r Readable [ -r file ]
-w Writable [ -w file ]
-x Executable [ -x script ]

case Statement

#!/bin/bash

echo "Select an option:"
echo "1) List files"
echo "2) Show current time"
echo "3) Show system info"
echo "4) Exit"

read -p "Choice (1-4): " choice

case $choice in
    1)
        echo "=== File List ==="
        ls -la
        ;;
    2)
        echo "=== Current Time ==="
        date
        ;;
    3)
        echo "=== System Info ==="
        uname -a
        ;;
    4)
        echo "Exiting."
        exit 0
        ;;
    *)
        echo "Invalid choice."
        ;;
esac

Loops

Conclusion: {1..N} for ranges, while IFS= read for file lines, until for inverse conditions.

for Loop

Basic for Loop

#!/bin/bash

# Numeric range
for i in {1..5}
do
    echo "Count: $i"
done

echo "---"

# File processing
for file in *.txt
do
    echo "Processing: $file"
    wc -l "$file"
done

Loop with Arrays

#!/bin/bash

fruits=("apple" "banana" "orange" "grape")

echo "Fruit list:"
for fruit in "${fruits[@]}"
do
    echo "- $fruit"
done

C-style for Loop

#!/bin/bash

echo "Multiplication table (partial):"
for ((i=1; i<=5; i++))
do
    for ((j=1; j<=5; j++))
    do
        result=$((i * j))
        printf "%2d " $result
    done
    echo
done

while Loop

Basic while Loop

#!/bin/bash

count=1
while [ $count -le 5 ]
do
    echo "Loop iteration $count"
    count=$((count + 1))
done

Reading Files

#!/bin/bash

filename="data.txt"

if [ -f "$filename" ]; then
    while IFS= read -r line
    do
        echo "Read: $line"
    done < "$filename"
else
    echo "File $filename not found"
fi

until Loop

#!/bin/bash

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

Loop Control

  • break — Exit loop
  • continue — Skip to next iteration
#!/bin/bash

for i in {1..10}
do
    if [ $i -eq 3 ]; then
        echo "Skipping 3"
        continue
    fi

    if [ $i -eq 8 ]; then
        echo "Stopping at 8"
        break
    fi

    echo "Number: $i"
done

Common Beginner Mistakes and Pitfalls

Conclusion: Six traps in Bash scripts: spacing, braces, brackets, quotes, backticks, math.

Mistake 1: Spaces in Variable Assignment

NG (causes error)

name = "Taro"     # Space before/after =
age= 25          # Space after =
city ="Tokyo"     # Space before =

Results in "command not found" error.

OK (correct usage)

name="Taro"      # No spaces around =
age=25
city="Tokyo"

Variable assignment must have no spaces around =.

Mistake 2: Missing Braces in Variable Reference

NG (unexpected results)

filename="test"
echo "$filenameback.txt"    # Empty
echo "$filename_backup"     # Empty

OK (correct usage)

filename="test"
echo "${filename}back.txt"   # testback.txt
echo "${filename}_backup"    # test_backup

Use {} to clearly define variable name scope.

Mistake 3: Missing Spaces in if Statement Conditions

NG (syntax error)

if [$num -gt 5]; then       # No space after [
if [ $num -gt 5]; then      # No space before ]

OK (correct usage)

if [ $num -gt 5 ]; then     # Spaces inside [ ] required
if [[ $num -gt 5 ]]; then   # Same for [[ ]]
if (( num > 5 )); then      # Arithmetic expression

Mistake 4: Missing Quotes in String Comparison

NG (dangerous examples)

if [ $name = John Doe ]; then    # Issues with spaces
if [ $empty_var = "" ]; then     # Error when empty

OK (safe usage)

if [ "$name" = "John Doe" ]; then    # Quote both sides
if [ "$empty_var" = "" ]; then       # No error when empty
if [ -z "$var" ]; then               # Dedicated empty check option

Mistake 5: Old Command Substitution Syntax

NG (not recommended)

date=`date`                 # Backticks
result=`cat `which ls``     # Nesting causes error

OK (modern syntax)

date=$(date)                # Use $()
result=$(cat $(which ls))   # Easy to nest

Mistake 6: Arithmetic Operation Errors

NG (not calculated)

result = $num1 + $num2      # Interpreted as a "result" command (command not found)
sum="$a + $b"               # Not calculated

OK (correct calculation methods)

result=$((num1 + num2))     # Arithmetic expansion
let "result = num1 + num2"  # Use let command

Basic Rules to Prevent Mistakes

Writing Basics

  • Variable assignment: no spaces around =
  • Variable usage: always quote "$var"
  • Complex variables: use braces "${var}"

Conditional Basics

  • Using [ ]: always include internal spaces
  • String comparison: quote both sides
  • Numeric comparison: use -eq, -gt, -lt, etc.

Debugging and Troubleshooting

#!/bin/bash

# Enable debug mode
set -x              # Display command execution
set -e              # Stop on error
set -u              # Error on undefined variables

# Check variable contents
echo "DEBUG: var = [$var]"

# Check file existence
if [ ! -f "$filename" ]; then
    echo "ERROR: File $filename not found" >&2
    exit 1
fi

Common Error Messages and Solutions

  • "command not found": Unnecessary spaces in variable assignment, missing execute permission → chmod +x script.sh
  • "syntax error": Missing spaces inside [ ] in if statement, quote mismatch, missing keywords (then, fi, done)
  • "Permission denied": No execute permission → chmod +x script.sh

Next Reading