Shell Scripting Basics

Shell Scripting Basics

Shell scripting allows you to automate tasks, combine commands, and create powerful tools on Linux systems. Whether you’re a system administrator, developer, or power user, learning shell scripting will greatly enhance your productivity. This tutorial covers the fundamentals of bash scripting, from basic scripts to more advanced concepts.

What is Shell Scripting?

Shell scripting is writing a series of commands for the shell to execute. The most common shell on Linux is Bash (Bourne Again SHell). Scripts are text files containing commands that would normally be entered interactively at the command prompt.

Creating Your First Script

Basic Script Structure

#!/bin/bash
# This is a comment
echo "Hello, World!"

Making Scripts Executable

# Create the script
nano hello.sh

# Make it executable
chmod +x hello.sh

# Run the script
./hello.sh

Variables

Declaring Variables

#!/bin/bash

# String variables
name="John"
echo "Hello, $name!"

# Numeric variables
age=25
echo "Age: $age"

# Command substitution
current_date=$(date)
echo "Today is: $current_date"

Variable Naming Rules

  • Start with letter or underscore
  • Contain letters, numbers, underscores
  • Case sensitive
  • No spaces around =

Special Variables

#!/bin/bash

echo "Script name: $0"
echo "First argument: $1"
echo "Second argument: $2"
echo "All arguments: $@"
echo "Number of arguments: $#"
echo "Process ID: $$"
echo "Exit status of last command: $?"

Command Line Arguments

#!/bin/bash

# Check if arguments are provided
if [ $# -eq 0 ]; then
    echo "Usage: $0 <name> [age]"
    exit 1
fi

name=$1
age=${2:-"unknown"}  # Default value if not provided

echo "Name: $name"
echo "Age: $age"

Conditional Statements

if-else Statements

#!/bin/bash

read -p "Enter a number: " num

if [ $num -gt 10 ]; then
    echo "Number is greater than 10"
elif [ $num -eq 10 ]; then
    echo "Number is equal to 10"
else
    echo "Number is less than 10"
fi

File Testing

#!/bin/bash

filename="test.txt"

if [ -f "$filename" ]; then
    echo "File exists"
elif [ -d "$filename" ]; then
    echo "Directory exists"
else
    echo "Neither file nor directory exists"
fi

String Comparison

#!/bin/bash

read -p "Enter your name: " name

if [ "$name" = "admin" ]; then
    echo "Welcome, administrator!"
elif [ -z "$name" ]; then
    echo "Name cannot be empty"
else
    echo "Hello, $name!"
fi

Loops

for Loops

#!/bin/bash

# Loop through arguments
for arg in "$@"; do
    echo "Argument: $arg"
done

# Loop through files
for file in *.txt; do
    echo "Processing $file"
    wc -l "$file"
done

# C-style for loop
for ((i=1; i<=5; i++)); do
    echo "Number: $i"
done

while Loops

#!/bin/bash

counter=1
while [ $counter -le 5 ]; do
    echo "Count: $counter"
    ((counter++))
done

# Reading a file line by line
while IFS= read -r line; do
    echo "Line: $line"
done < input.txt

until Loops

#!/bin/bash

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

Functions

Basic Functions

#!/bin/bash

# Function definition
greet() {
    echo "Hello, $1!"
}

# Function call
greet "World"
greet "Alice"

Functions with Return Values

#!/bin/bash

# Function that returns a value
is_even() {
    if [ $(($1 % 2)) -eq 0 ]; then
        return 0  # Success (true)
    else
        return 1  # Failure (false)
    fi
}

# Usage
read -p "Enter a number: " num

if is_even $num; then
    echo "$num is even"
else
    echo "$num is odd"
fi

Functions with Local Variables

#!/bin/bash

calculate_area() {
    local length=$1
    local width=$2
    local area=$((length * width))
    echo $area
}

result=$(calculate_area 10 5)
echo "Area: $result"

Input and Output

Reading User Input

#!/bin/bash

# Basic input
read -p "Enter your name: " name
echo "Hello, $name!"

# Silent input (for passwords)
read -s -p "Enter password: " password
echo  # New line after silent input

# Read multiple values
read -p "Enter first and last name: " first last
echo "First: $first, Last: $last"

File Input/Output

#!/bin/bash

# Writing to a file
echo "This is line 1" > output.txt
echo "This is line 2" >> output.txt

# Reading from a file
while IFS= read -r line; do
    echo "Read: $line"
done < output.txt

# Here document
cat << EOF > config.txt
server=localhost
port=8080
timeout=30
EOF

Error Handling

Exit Codes

#!/bin/bash

# Function that might fail
backup_file() {
    if cp "$1" "$1.bak"; then
        echo "Backup created successfully"
        return 0
    else
        echo "Backup failed" >&2
        return 1
    fi
}

# Usage
if backup_file important.txt; then
    echo "Proceeding with next steps..."
else
    echo "Cannot proceed without backup"
    exit 1
fi

Trap Signals

#!/bin/bash

# Cleanup function
cleanup() {
    echo "Cleaning up temporary files..."
    rm -f /tmp/temp_*.txt
    exit
}

# Set trap for common signals
trap cleanup INT TERM EXIT

echo "Script running... Press Ctrl+C to test cleanup"
sleep 10

Practical Examples

System Information Script

#!/bin/bash

echo "=== System Information ==="
echo "Hostname: $(hostname)"
echo "OS: $(uname -s) $(uname -r)"
echo "Uptime: $(uptime -p)"
echo "Memory: $(free -h | grep '^Mem:' | awk '{print $3 "/" $2}')"
echo "Disk Usage: $(df -h / | tail -1 | awk '{print $5}')"

File Backup Script

#!/bin/bash

# Backup script with error handling
SOURCE_DIR="/home/user/documents"
BACKUP_DIR="/home/user/backup"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)

if [ ! -d "$SOURCE_DIR" ]; then
    echo "Source directory does not exist: $SOURCE_DIR" >&2
    exit 1
fi

mkdir -p "$BACKUP_DIR"

tar -czf "$BACKUP_DIR/backup_$TIMESTAMP.tar.gz" -C "$SOURCE_DIR" . 2>/dev/null

if [ $? -eq 0 ]; then
    echo "Backup completed: $BACKUP_DIR/backup_$TIMESTAMP.tar.gz"
else
    echo "Backup failed" >&2
    exit 1
fi

Simple Calculator

#!/bin/bash

calculate() {
    case $2 in
        +) echo $(($1 + $3)) ;;
        -) echo $(($1 - $3)) ;;
        \*) echo $(($1 * $3)) ;;
        /) 
            if [ $3 -eq 0 ]; then
                echo "Division by zero!" >&2
                return 1
            fi
            echo $(($1 / $3)) 
            ;;
        *) echo "Invalid operator" >&2; return 1 ;;
    esac
}

if [ $# -ne 3 ]; then
    echo "Usage: $0 <num1> <operator> <num2>"
    echo "Operators: +, -, *, /"
    exit 1
fi

result=$(calculate $1 "$2" $3)
if [ $? -eq 0 ]; then
    echo "$1 $2 $3 = $result"
fi

Best Practices

  1. Use meaningful variable names
  2. Add comments to explain complex logic
  3. Handle errors gracefully
  4. Use double quotes around variables
  5. Test scripts with different inputs
  6. Use functions for reusable code
  7. Check for required arguments
  8. Use consistent indentation

Common Mistakes to Avoid

Unquoted Variables

# Bad - word splitting can occur
echo $filename

# Good - preserves spaces and special characters
echo "$filename"

Missing Exit Codes

# Bad - script appears successful even on failure
some_command_that_might_fail

# Good - propagate error status
some_command_that_might_fail || exit 1

Not Checking Command Results

# Bad - continues even if mkdir fails
mkdir /important/directory
echo "success" > /important/directory/file.txt

# Good - check result
if mkdir /important/directory; then
    echo "success" > /important/directory/file.txt
else
    echo "Failed to create directory" >&2
    exit 1
fi

Debugging Scripts

Debug Mode

#!/bin/bash -x  # Enable debug mode

# Or enable debugging for specific sections
set -x
some_command
set +x

Verbose Output

#!/bin/bash

# Add debug information
echo "Starting script execution"
echo "Arguments: $@"
echo "Working directory: $(pwd)"

# Your script logic here

Summary

Shell scripting is a powerful skill that can automate repetitive tasks and create complex workflows. Key concepts include:

  • Variables for storing data
  • Conditionals for decision making
  • Loops for repetition
  • Functions for code organization
  • Input/Output for user interaction and file operations
  • Error handling for robust scripts

With practice, you’ll be able to write scripts that save time and reduce errors in your daily Linux usage.


External Resources:

Related Tutorials:

  • Learn basic Linux commands here to understand the commands you’ll use in scripts.
  • Check out installing i3 window manager here for customizing your Linux desktop environment.
Last updated on