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.shVariables
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"
fiFile 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"
fiString 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!"
fiLoops
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"
donewhile 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.txtuntil Loops
#!/bin/bash
counter=1
until [ $counter -gt 5 ]; do
echo "Count: $counter"
((counter++))
doneFunctions
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"
fiFunctions 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
EOFError 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
fiTrap 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 10Practical 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
fiSimple 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"
fiBest Practices
- Use meaningful variable names
- Add comments to explain complex logic
- Handle errors gracefully
- Use double quotes around variables
- Test scripts with different inputs
- Use functions for reusable code
- Check for required arguments
- 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 1Not 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
fiDebugging Scripts
Debug Mode
#!/bin/bash -x # Enable debug mode
# Or enable debugging for specific sections
set -x
some_command
set +xVerbose Output
#!/bin/bash
# Add debug information
echo "Starting script execution"
echo "Arguments: $@"
echo "Working directory: $(pwd)"
# Your script logic hereSummary
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: