Shell Scripting Basics
What is a Shell Script?
A shell script is a text file containing a series of commands that is interpreted and executed by a Shell. It can automate repetitive tasks, batch process files, manage systems, and more.
Creating Your First Script
Writing the Script
#!/bin/bash
# My first script
# Author: Maxwell
# Date: 2025-01-09
echo "Hello, World!"
echo "Current time: $(date)"
echo "Current user: $USER"
echo "Current directory: $PWD"
Shebang
The #! at the beginning of the script is called the Shebang, which specifies the interpreter:
#!/bin/bash # Use bash
#!/bin/sh # Use sh
#!/usr/bin/env bash # Recommended, uses bash from environment
#!/usr/bin/env python3 # Python script
Running the Script
# Method 1: Add execute permission
$ chmod +x script.sh
$ ./script.sh
# Method 2: Run with bash
$ bash script.sh
# Method 3: Use source (execute in current shell)
$ source script.sh
$ . script.sh
Variables
Defining and Using Variables
#!/bin/bash
# Define variables (no spaces around =)
name="Maxwell"
age=25
path="/home/maxwell"
# Use variables
echo "Name: $name"
echo "Age: ${age}"
echo "Path: ${path}/documents"
# Read-only variables
readonly PI=3.14159
# Delete variable
unset age
Variable Types
# String
str="Hello World"
# Number (actually all are strings)
num=42
# Array
arr=(one two three)
echo ${arr[0]} # one
echo ${arr[@]} # all elements
echo ${#arr[@]} # array length
Special Variables
#!/bin/bash
echo "Script name: $0"
echo "First parameter: $1"
echo "Second parameter: $2"
echo "Parameter count: $#"
echo "All parameters: $@"
String Operations
str="Hello World"
# Length
echo ${#str} # 11
# Substring
echo ${str:0:5} # Hello
echo ${str:6} # World
# Replacement
echo ${str/World/Bash} # Hello Bash
echo ${str//o/O} # HellO WOrld (all replacement)
# Deletion
filename="document.txt.bak"
echo ${filename%.bak} # document.txt (delete from right)
echo ${filename%%.*} # document (greedy)
echo ${filename#*.} # txt.bak (delete from left)
echo ${filename##*.} # bak (greedy)
# Default value
echo ${undefined:-default} # Use default if variable is undefined
echo ${undefined:=default} # Set default if variable is undefined
echo ${undefined:?error msg} # Error if undefined
Quotes
Single Quotes
Content inside single quotes is output literally, variables are not expanded:
name="Maxwell"
echo 'Hello $name' # Hello $name
Double Quotes
Variables and command substitution are expanded inside double quotes:
name="Maxwell"
echo "Hello $name" # Hello Maxwell
echo "Today is $(date +%Y-%m-%d)"
Backticks and $()
Command substitution:
# Backticks (old syntax)
today=`date +%Y-%m-%d`
# $() (recommended)
today=$(date +%Y-%m-%d)
files=$(ls -la)
Arithmetic Operations
$(()) Syntax
a=10
b=3
echo $((a + b)) # 13
echo $((a - b)) # 7
echo $((a * b)) # 30
echo $((a / b)) # 3
echo $((a % b)) # 1
echo $((a ** b)) # 1000 (power operation)
# Increment/decrement
((a++))
((b--))
((a += 5))
let Command
let "a = 10 + 5"
let "a++"
expr Command
result=$(expr 10 + 5)
result=$(expr 10 \* 5) # Multiplication needs escaping
bc Calculator (Floating Point)
# Integer division
echo $((10 / 3)) # 3
# Floating-point division
echo "scale=2; 10 / 3" | bc # 3.33
# Complex calculations
result=$(echo "scale=4; sqrt(2)" | bc)
Conditional Statements
if Statement
#!/bin/bash
if [ condition ]; then
command
fi
if [ condition ]; then
command1
else
command2
fi
if [ condition1 ]; then
command1
elif [ condition2 ]; then
command2
else
command3
fi
Conditional Expressions
File Tests
if [ -f "/etc/passwd" ]; then
echo "File exists"
fi
if [ -d "/home" ]; then
echo "Directory exists"
fi
String Tests
name="Maxwell"
if [ -n "$name" ]; then
echo "Name is not empty"
fi
if [ "$name" = "Maxwell" ]; then
echo "Name matches"
fi
Numeric Comparisons
age=25
if [ $age -ge 18 ]; then
echo "Adult"
fi
Logical Operations
# AND
if [ condition1 ] && [ condition2 ]; then
if [ condition1 -a condition2 ]; then
# OR
if [ condition1 ] || [ condition2 ]; then
if [ condition1 -o condition2 ]; then
# NOT
if [ ! condition ]; then
[[ ]] Extended Test
[[ ]] is a Bash extension with more powerful features:
# Support regex matching
if [[ "$str" =~ ^[0-9]+$ ]]; then
echo "Is a number"
fi
# Support pattern matching
if [[ "$file" == *.txt ]]; then
echo "Is a text file"
fi
# Safer string comparison
if [[ "$name" == "Maxwell" ]]; then
echo "Matches"
fi
case Statement
#!/bin/bash
case $1 in
start)
echo "Start service"
;;
stop)
echo "Stop service"
;;
restart)
echo "Restart service"
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esac
Loops
for Loop
# List loop
for item in item1 item2 item3; do
echo $item
done
# Array loop
arr=(one two three)
for item in ${arr[@]}; do
echo $item
done
# File loop
for file in *.txt; do
echo "Processing: $file"
done
# Range loop
for i in {1..5}; do
echo $i
done
# C-style loop
for ((i=0; i<5; i++)); do
echo $i
done
# Command output loop
for user in $(cat /etc/passwd | cut -d: -f1); do
echo "User: $user"
done
while Loop
#!/bin/bash
count=0
while [ $count -lt 5 ]; do
echo "Count: $count"
((count++))
done
# Read file
while IFS= read -r line; do
echo "Line: $line"
done < file.txt
# Infinite loop
while true; do
echo "Running..."
sleep 1
done
until Loop
count=0
until [ $count -ge 5 ]; do
echo "Count: $count"
((count++))
done
Loop Control
# break - exit loop
for i in {1..10}; do
if [ $i -eq 5 ]; then
break
fi
echo $i
done
# continue - skip current iteration
for i in {1..5}; do
if [ $i -eq 3 ]; then
continue
fi
echo $i
done
Functions
Defining and Calling
#!/bin/bash
# Define function
function greet() {
echo "Hello, $1!"
}
# Or (POSIX compatible)
greet() {
echo "Hello, $1!"
}
# Call function
greet "Maxwell"
greet "World"
Function Parameters and Return Values
#!/bin/bash
add() {
local a=$1
local b=$2
local sum=$((a + b))
echo $sum # Return value via echo
}
# Get return value
result=$(add 3 5)
echo "Result: $result"
# Use return (can only return 0-255)
check_file() {
if [ -f "$1" ]; then
return 0
else
return 1
fi
}
if check_file "/etc/passwd"; then
echo "File exists"
fi
Local Variables
#!/bin/bash
global_var="global"
my_function() {
local local_var="local"
global_var="Modified in function"
echo "Inside function: $local_var, $global_var"
}
my_function
echo "Outside function: $global_var"
echo "Outside function: $local_var" # Empty (local variable not visible)
#!/bin/bash
# Basic read
echo -n "Please enter name: "
read name
echo "Hello, $name"
# With prompt
read -p "Please enter age: " age
# Hide input (password)
read -sp "Please enter password: " password
echo
# Set timeout
read -t 5 -p "Enter within 5 seconds: " answer
# Read into array
read -a arr -p "Enter multiple values: "
echo "First: ${arr[0]}"
Output
# echo
echo "Normal output"
echo -n "No newline"
echo -e "Support\ttab\newline\ncharacters"
# printf (formatted output)
printf "Name: %s, Age: %d\n" "Maxwell" 25
printf "%-10s %5d\n" "Item" 100
Practical Examples
Backup Script
#!/bin/bash
BACKUP_DIR="/backup"
SOURCE_DIR="/var/www"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/www_${DATE}.tar.gz"
# Create backup directory
mkdir -p "$BACKUP_DIR"
# Create backup
tar -czf "$BACKUP_FILE" "$SOURCE_DIR"
if [ $? -eq 0 ]; then
echo "Backup successful: $BACKUP_FILE"
else
echo "Backup failed"
exit 1
fi
# Delete backups 7 days old
find "$BACKUP_DIR" -name "www_*.tar.gz" -mtime +7 -delete
System Monitoring Script
#!/bin/bash
echo "=== System Information ==="
echo "Hostname: $(hostname)"
echo "System: $(uname -s)"
echo "Kernel: $(uname -r)"
echo
echo "=== CPU Usage ==="
top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d% -f1
echo
echo "=== Memory Usage ==="
free -h | grep Mem
echo
echo "=== Disk Usage ==="
df -h | grep -v tmpfs
Summary
This chapter introduced shell scripting basics:
- Script structure: Shebang, comments, execution
- Variables: Definition, usage, special variables
- Operations: Arithmetic, string operations
- Conditionals: if, case, test expressions
- Loops: for, while, until
- Functions: Definition, parameters, return values
- Input/Output: read, echo, printf
Shell scripting is the foundation of Linux automation. Mastering it will greatly improve your work efficiency.
Previous chapter: SSH Remote Connection
Next chapter: Environment Variables