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
bash
#!/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:
bash
#!/bin/bash # Use bash
#!/bin/sh # Use sh
#!/usr/bin/env bash # Recommended, uses bash from environment
#!/usr/bin/env python3 # Python scriptRunning the Script
bash
# 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.shVariables
Defining and Using Variables
bash
#!/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 ageVariable Types
bash
# 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 lengthSpecial Variables
| Variable | Description |
|---|---|
$0 | Script name |
$1-$9 | Positional parameters |
${10} | 10th and subsequent parameters |
$# | Number of parameters |
$@ | All parameters (as independent strings) |
$* | All parameters (as single string) |
$? | Exit status of previous command |
$$ | PID of current script |
$! | PID of last background process |
bash
#!/bin/bash
echo "Script name: $0"
echo "First parameter: $1"
echo "Second parameter: $2"
echo "Parameter count: $#"
echo "All parameters: $@"String Operations
bash
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 undefinedQuotes
Single Quotes
Content inside single quotes is output literally, variables are not expanded:
bash
name="Maxwell"
echo 'Hello $name' # Hello $nameDouble Quotes
Variables and command substitution are expanded inside double quotes:
bash
name="Maxwell"
echo "Hello $name" # Hello Maxwell
echo "Today is $(date +%Y-%m-%d)"Backticks and $()
Command substitution:
bash
# Backticks (old syntax)
today=`date +%Y-%m-%d`
# $() (recommended)
today=$(date +%Y-%m-%d)
files=$(ls -la)Arithmetic Operations
$(()) Syntax
bash
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
bash
let "a = 10 + 5"
let "a++"expr Command
bash
result=$(expr 10 + 5)
result=$(expr 10 \* 5) # Multiplication needs escapingbc Calculator (Floating Point)
bash
# 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
bash
#!/bin/bash
if [ condition ]; then
command
fi
if [ condition ]; then
command1
else
command2
fi
if [ condition1 ]; then
command1
elif [ condition2 ]; then
command2
else
command3
fiConditional Expressions
File Tests
| Expression | Description |
|---|---|
-e file | File exists |
-f file | Is regular file |
-d file | Is directory |
-r file | Is readable |
-w file | Is writable |
-x file | Is executable |
-s file | File is not empty |
-L file | Is symbolic link |
bash
if [ -f "/etc/passwd" ]; then
echo "File exists"
fi
if [ -d "/home" ]; then
echo "Directory exists"
fiString Tests
| Expression | Description |
|---|---|
-z str | String is empty |
-n str | String is not empty |
str1 = str2 | Strings are equal |
str1 != str2 | Strings are not equal |
bash
name="Maxwell"
if [ -n "$name" ]; then
echo "Name is not empty"
fi
if [ "$name" = "Maxwell" ]; then
echo "Name matches"
fiNumeric Comparisons
| Expression | Description |
|---|---|
n1 -eq n2 | Equal |
n1 -ne n2 | Not equal |
n1 -gt n2 | Greater than |
n1 -ge n2 | Greater or equal |
n1 -lt n2 | Less than |
n1 -le n2 | Less or equal |
bash
age=25
if [ $age -ge 18 ]; then
echo "Adult"
fiLogical Operations
bash
# 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:
bash
# 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"
ficase Statement
bash
#!/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
;;
esacLoops
for Loop
bash
# 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"
donewhile Loop
bash
#!/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
doneuntil Loop
bash
count=0
until [ $count -ge 5 ]; do
echo "Count: $count"
((count++))
doneLoop Control
bash
# 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
doneFunctions
Defining and Calling
bash
#!/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
bash
#!/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"
fiLocal Variables
bash
#!/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)Input/Output
Reading User Input
bash
#!/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
bash
# 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" 100Practical Examples
Backup Script
bash
#!/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 -deleteSystem Monitoring Script
bash
#!/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 tmpfsSummary
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