_____ _ ___ _________ __ |_ _|__ _ __ _ __ ___ (_)_ __ __ _| \ \ / / ____\ \/ / | |/ _ \ '__| '_ ` _ \| | '_ \ / _` | |\ \ / /| _| \ / | | __/ | | | | | | | | | | | (_| | | \ V / | |___ / \ |_|\___|_| |_| |_| |_|_|_| |_|\__,_|_| \_/ |_____/_/\_\
A shell script is a programming method that allows a series of terminal commands to be written in a file and executed sequentially. When you save commands that you repeatedly type in the terminal into a file, you have essentially created a shell script. Shell scripting is a fundamental skill used in many areas from system administration to software development, from DevOps processes to data processing.
The biggest advantage of shell scripts is that they can be executed directly without any compilation step. The commands you write are interpreted and executed line by line. This makes it ideal for rapid prototyping and automation. Bash (Bourne Again Shell) is the most commonly used shell on Linux and macOS systems, and this guide will focus on Bash scripting.
The first line of every shell script should begin with a shebang (#!). This line tells the operating system which interpreter should be used to run the script.
#!/bin/bash
# This is a Bash script
echo "Hello World!"
echo "This is my first shell script."
# 1. Create the file
$ nano hello.sh
# 2. Give it execute permission
$ chmod +x hello.sh
# 3. Run the script
$ ./hello.sh
# Alternatively, run directly with bash
$ bash hello.sh
The chmod +x command gives the file execute permission. Without this step, the ./hello.sh command will produce a "Permission denied" error. Alternatively, you can run it through the Bash interpreter directly using bash hello.sh.
Variables are used to temporarily store data. In Bash, it is important not to leave spaces around the = sign when defining variables.
#!/bin/bash
# Variable definition (NO spaces!)
name="Ali"
age=25
profession="Developer"
# Using variables ($)
echo "Hello, my name is $name"
echo "I am $age years old and I work as a $profession"
# Clarifying with curly braces
file="report"
echo "${file}_2026.txt"
# Assigning command output to a variable
today=$(date +%Y-%m-%d)
user=$(whoami)
echo "Date: $today, User: $user"
# Read-only variable
readonly PI=3.14159
# PI=3.14 # This will cause an error!
# Environment variables
echo "Home directory: $HOME"
echo "User: $USER"
echo "Shell: $SHELL"
The read command is used to get input from the user.
#!/bin/bash
# Simple input
echo "What is your name?"
read name
echo "Hello, $name!"
# Input with prompt (-p)
read -p "Your age: " age
echo "You are $age years old."
# Hidden input for passwords (-s)
read -s -p "Enter your password: " password
echo ""
echo "Password received."
# Input with timeout (-t)
read -t 10 -p "Respond within 10 seconds: " answer
Conditional statements allow different code blocks to be executed based on specific conditions. In Bash, conditions are written inside [ ] or [[ ]].
#!/bin/bash
# Basic if/else structure
read -p "Enter a number: " number
if [ $number -gt 0 ]; then
echo "$number is a positive number."
elif [ $number -lt 0 ]; then
echo "$number is a negative number."
else
echo "The number you entered is zero."
fi
# Numeric comparison operators:
# -eq (equal), -ne (not equal)
# -gt (greater than), -lt (less than)
# -ge (greater or equal), -le (less or equal)
# String comparison
name="Ali"
if [ "$name" = "Ali" ]; then
echo "Welcome Ali!"
fi
# File checks
file="/etc/hosts"
if [ -f "$file" ]; then
echo "$file exists."
elif [ -d "$file" ]; then
echo "$file is a directory."
else
echo "$file was not found."
fi
# -f: is file?, -d: is directory?, -e: exists?
# -r: readable?, -w: writable?, -x: executable?
# Logical operators
age=20
if [ $age -ge 18 ] && [ $age -le 65 ]; then
echo "You are of working age."
fi
#!/bin/bash
# Loop over a list
for fruit in apple pear cherry orange; do
echo "Fruit: $fruit"
done
# Loop over a number range
for i in {1..10}; do
echo "Number: $i"
done
# Stepped number range (by 2s)
for i in {0..20..2}; do
echo "Even number: $i"
done
# C-style for loop
for ((i=0; i<5; i++)); do
echo "Index: $i"
done
# Loop over files
for file in *.txt; do
echo "File: $file"
echo "Size: $(wc -c < "$file") bytes"
done
# Loop over command output
for user in $(cat /etc/passwd | cut -d: -f1); do
echo "User: $user"
done
#!/bin/bash
# Simple while loop
counter=1
while [ $counter -le 5 ]; do
echo "Counter: $counter"
counter=$((counter + 1))
done
# Read a file line by line
while IFS= read -r line; do
echo "Line: $line"
done < file.txt
# Infinite loop (stop with Ctrl+C)
while true; do
read -p "Type 'q' to quit: " input
if [ "$input" = "q" ]; then
echo "Exiting..."
break
fi
echo "You entered: $input"
done
Functions are used to organize and reuse repeating blocks of code.
#!/bin/bash
# Function definition
greet() {
echo "Hello, $1! Welcome."
}
# Function call
greet "Ali"
greet "Ayse"
# Function with parameters
add() {
local result=$(( $1 + $2 ))
echo $result
}
# Using function return value
result=$(add 15 27)
echo "Sum: $result"
# Multiple parameters
show_info() {
local name=$1
local age=$2
local city=$3
echo "Name: $name, Age: $age, City: $city"
}
show_info "Mehmet" 30 "Istanbul"
#!/bin/bash
# Check if file exists and create it
file="record.log"
if [ ! -f "$file" ]; then
touch "$file"
echo "File created: $file"
fi
# Write to file
echo "$(date): Script started" >> "$file"
# Check file size
size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null)
echo "File size: $size bytes"
# Backup creation script
create_backup() {
local source=$1
local target="${source}.bak.$(date +%Y%m%d)"
cp "$source" "$target"
echo "Backup created: $target"
}
create_backup "config.txt"
#!/bin/bash
echo "=============================="
echo " System Information Report"
echo "=============================="
echo "Date : $(date)"
echo "Hostname : $(hostname)"
echo "User : $(whoami)"
echo "OS : $(uname -s)"
echo "Kernel : $(uname -r)"
echo "Uptime : $(uptime -p 2>/dev/null || uptime)"
echo "Disk Usage:"
df -h / | tail -1
echo "Memory Usage:"
free -h 2>/dev/null || vm_stat
echo "=============================="
#!/bin/bash
# Change .jpeg extensions to .jpg
for file in *.jpeg; do
[ -f "$file" ] || continue
new_name="${file%.jpeg}.jpg"
mv "$file" "$new_name"
echo "Renamed: $file -> $new_name"
done
#!/bin/bash
# Stop the script on error
set -e
# Error on undefined variable usage
set -u
# Error trapping
handle_error() {
echo "ERROR: An error occurred on line $1."
exit 1
}
trap 'handle_error $LINENO' ERR
# Checking exit code
if ! some_command 2>/dev/null; then
echo "Command failed, trying alternative..."
fi
Shell scripting is a powerful skill that takes terminal usage to the next level. By writing scripts that start with a shebang line and contain variables, conditionals, loops, and functions, you can automate repetitive tasks. You can read user input with read, perform file operations, and implement error handling. With every script you write, you will learn something new and make your workflow more efficient. Keep practicing to develop your shell scripting skills further.