0% found this document useful (0 votes)
3 views43 pages

Unix Shell Scripting Complete Guide

The document is a comprehensive reference guide for UNIX and Linux shell scripting, covering fundamental concepts, commands, file permissions, process management, and advanced scripting techniques. It includes detailed sections on file and directory commands, text processing, searching and filtering, and networking commands. The guide serves as a practical resource for users looking to enhance their skills in shell scripting and UNIX system management.

Uploaded by

amosmaritim123
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views43 pages

Unix Shell Scripting Complete Guide

The document is a comprehensive reference guide for UNIX and Linux shell scripting, covering fundamental concepts, commands, file permissions, process management, and advanced scripting techniques. It includes detailed sections on file and directory commands, text processing, searching and filtering, and networking commands. The guide serves as a practical resource for users looking to enhance their skills in shell scripting and UNIX system management.

Uploaded by

amosmaritim123
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

UNIX / LINUX
Shell Scripting
Complete Reference Guide

Commands • Examples • Shell Scripting • Data Types


Control Flow • Functions • Arrays • File I/O • Advanced Topics

Comprehensive study notes for Unix & Shell Scripting


Table of Contents
1. Unix Fundamentals — The Shell & File System
2. File & Directory Commands
3. File Permissions & Ownership
4. Process Management
5. Text Processing Commands
6. Searching & Filtering
7. Networking Commands
8. Archiving & Compression
9. Disk & System Monitoring
10. Redirection, Pipes & Special Characters
11. Shell Scripting — Introduction
12. Variables & Data Types
13. Operators
14. Control Flow — if / elif / else
15. Loops — for, while, until
16. case Statement
17. Functions
18. Arrays
19. String Manipulation
20. File I/O in Scripts
21. Error Handling & Debugging
22. Regular Expressions
23. Advanced Topics & Best Practices

Unix & Shell Scripting — Complete Reference Page 2


1. Unix Fundamentals — The Shell & File
System
Unix is a multiuser, multitasking operating system. The shell is a command-line interpreter that acts as the
interface between the user and the kernel. Common shells include bash (Bourne Again Shell), sh, zsh, ksh,
and csh.

Unix File System Hierarchy


Command / Syntax Description & Notes

/ Root directory — top of the file system tree

/home Home directories for regular users

/root Home directory for the root (superuser)

/bin Essential user binaries (ls, cp, mv …)

/usr/bin Non-essential user binaries

/sbin System binaries (used by root)

/etc System-wide configuration files

/var Variable data: logs, spools, tmp files

/tmp Temporary files (cleared on reboot)

/dev Device files (disks, terminals …)

/proc Virtual filesystem — kernel & process info

/lib Shared libraries needed by /bin & /sbin

/mnt Mount point for temporary filesystems

/opt Optional/third-party software packages

Getting Help
Command / Syntax Description & Notes

man ls Open the manual page for the ls command

ls --help Quick help / usage summary

info bash GNU info documentation for bash

whatis ls One-line description of command

whereis ls Locate binary, source, and man pages

which python3 Show full path of command in PATH

type cd Show command type (builtin, alias, file …)

Unix & Shell Scripting — Complete Reference Page 3


2. File & Directory Commands
Navigation
Command / Syntax Description & Notes

pwd Print Working Directory — show current path

cd /path/to/dir Change to absolute path

cd .. Go up one directory level

cd ~ Go to home directory

cd - Toggle back to previous directory

ls List files in current directory

ls -l Long listing with permissions, size, date

ls -la Long listing including hidden files (dot files)

ls -lh Human-readable file sizes (KB, MB …)

ls -lt Sort by modification time, newest first

ls -R List recursively through subdirectories

ls -lS Sort by file size, largest first

tree Display directory structure as a tree

Creating, Copying, Moving & Deleting


Command / Syntax Description & Notes

touch [Link] Create empty file or update timestamp

mkdir mydir Create a new directory

mkdir -p a/b/c Create nested directories (no error if exists)

cp [Link] [Link] Copy file to destination

cp -r srcdir/ dstdir/ Copy directory recursively

cp -p file1 file2 Copy preserving permissions/timestamps

mv [Link] [Link] Rename file (or move to another location)

mv [Link] /tmp/ Move file to /tmp directory

rm [Link] Remove (delete) a file

rm -r mydir/ Remove directory and all contents recursively

rm -rf mydir/ Force remove without prompts — USE WITH CARE

rmdir emptydir/ Remove empty directory only

ln -s target linkname Create a symbolic (soft) link

ln target hardlink Create a hard link

Unix & Shell Scripting — Complete Reference Page 4


Viewing File Contents
Command / Syntax Description & Notes

cat [Link] Print entire file to stdout

cat -n [Link] Print file with line numbers

less [Link] Scroll through file (q to quit, / to search)

more [Link] Page through file (older, less features)

head [Link] Show first 10 lines

head -n 20 [Link] Show first 20 lines

tail [Link] Show last 10 lines

tail -n 30 [Link] Show last 30 lines

tail -f logfile Follow file — stream new lines as appended

wc [Link] Count lines, words, characters

wc -l [Link] Count lines only

wc -w [Link] Count words only

file [Link] Identify file type

stat [Link] Detailed file metadata (size, inode, times …)

Practical Examples
• Backup a config file: cp /etc/nginx/[Link] /etc/nginx/[Link]
• Find big files quickly: ls -lhS /var/log/ | head -20
• Watch a growing log: tail -f /var/log/syslog
• Count lines in a file: wc -l /etc/passwd → shows number of user accounts

Unix & Shell Scripting — Complete Reference Page 5


3. File Permissions & Ownership
Every file has three permission sets: owner (u), group (g), others (o). Each set has three bits: r (read=4), w
(write=2), x (execute=1).

-rwxr-xr-- 1 alice staff 4096 Jan 1 10:00 [Link]

• - = regular file (d = dir, l = symlink)


• rwx = owner has read+write+execute
• r-x = group has read+execute, no write
• r-- = others have read only

Command / Syntax Description & Notes

chmod 755 [Link] rwxr-xr-x — owner all, group/others read+exec

chmod 644 [Link] rw-r--r-- — owner read/write, others read

chmod 600 [Link] rw------- — owner read/write only (private key)

chmod +x [Link] Add execute permission for all

chmod u+x [Link] Add execute for owner only

chmod g-w [Link] Remove write from group

chmod o-rx [Link] Remove read+exec from others

chmod -R 755 mydir/ Apply permissions recursively

chown alice [Link] Change owner to alice

chown alice:staff [Link] Change owner and group

chown -R alice mydir/ Recursive ownership change

chgrp developers [Link] Change group only

umask Show default permission mask

umask 022 Set umask — new files get 644, dirs get 755

Special Permissions
Command / Syntax Description & Notes

chmod u+s exec SetUID — runs as file owner, not caller

chmod g+s dir/ SetGID — new files inherit directory group

chmod +t /tmp Sticky bit — only owner can delete their files

ls -l /tmp Notice 't' at end of permissions: drwxrwxrwt

sudo command Run command as root (superuser)

su - alice Switch to user alice (full login shell)

visudo Safely edit /etc/sudoers file


■ Octal quick-reference: 7=rwx 6=rw- 5=r-x 4=r-- 0=---

Unix & Shell Scripting — Complete Reference Page 6


4. Process Management
Command / Syntax Description & Notes

ps Snapshot of current user's processes

ps aux All processes, full detail (BSD style)

ps -ef All processes, full detail (System V style)

ps aux | grep nginx Find process by name

top Interactive process monitor (press q to quit)

htop Enhanced interactive process monitor

pgrep nginx Find PID by process name

kill PID Send SIGTERM (graceful stop) to process

kill -9 PID Send SIGKILL (force kill) to process

kill -l List all signal names

killall nginx Kill all processes named nginx

pkill -f pattern Kill processes matching pattern

jobs List background/stopped jobs in current shell

bg %1 Resume job 1 in background

fg %1 Bring job 1 to foreground

command & Run command in background

nohup cmd & Run command immune to hangup (survives logout)

nice -n 10 cmd Run with lower CPU priority (niceness 10)

renice -n 5 -p PID Change priority of running process

wait Wait for all background jobs to finish

sleep 5 Pause shell for 5 seconds

time command Measure execution time of command

Process States
Command / Syntax Description & Notes

R Running or runnable

S Interruptible sleep (waiting for event)

D Uninterruptible sleep (usually I/O)

Z Zombie — finished but not yet reaped by parent

T Stopped (e.g., by Ctrl+Z)

Signals Quick Reference


Command / Syntax Description & Notes

Unix & Shell Scripting — Complete Reference Page 7


SIGHUP (1) Hang up — reload config (used by daemons)

SIGINT (2) Interrupt — same as Ctrl+C

SIGKILL (9) Kill — cannot be caught or ignored

SIGTERM (15) Terminate — default, can be caught

SIGSTOP (19) Stop — cannot be caught; pauses process

SIGCONT (18) Continue — resumes a stopped process

Unix & Shell Scripting — Complete Reference Page 8


5. Text Processing Commands
echo & printf
Command / Syntax Description & Notes

echo "Hello World" Print text with trailing newline

echo -n "no newline" Print without trailing newline

echo -e "line1\nline2" Interpret escape sequences

printf "%-10s %5d\n" a 42 Formatted output (like C printf)

sort, uniq, cut, paste


Command / Syntax Description & Notes

sort [Link] Sort lines alphabetically

sort -n [Link] Sort numerically

sort -r [Link] Sort in reverse order

sort -k2 [Link] Sort by second field (column)

sort -u [Link] Sort and remove duplicates

uniq [Link] Remove consecutive duplicate lines

uniq -c [Link] Count occurrences of each line

uniq -d [Link] Show only duplicated lines

cut -d: -f1 /etc/passwd Cut field 1 using : as delimiter

cut -c1-5 [Link] Cut characters 1 through 5

paste file1 file2 Merge files side by side

tr — Translate Characters
Command / Syntax Description & Notes

tr 'a-z' 'A-Z' < file Convert lowercase to uppercase

tr -d '\n' < file Delete all newlines

tr -s ' ' < file Squeeze multiple spaces to one

tr -d '[:digit:]' < file Remove all digit characters

awk — Pattern Scanning & Reporting


Command / Syntax Description & Notes

awk '{print $1}' file Print first field of each line

awk '{print $1, $3}' file Print fields 1 and 3

awk -F: '{print $1}' /etc/passwd Use : as field separator

awk 'NR==3' file Print line number 3 only

Unix & Shell Scripting — Complete Reference Page 9


awk 'NR>=2 && NR<=5' file Print lines 2 to 5

awk '{sum+=$1} END{print sum}' Sum first column

awk '/pattern/{print}' file Print lines matching pattern

awk '{print NR, $0}' file Prefix each line with line number

awk 'END{print NR}' file Count total lines

sed — Stream Editor


Command / Syntax Description & Notes

sed 's/old/new/' file Replace first occurrence per line

sed 's/old/new/g' file Replace all occurrences (global)

sed -n '5p' file Print line 5 only (-n suppresses default)

sed '2,4d' file Delete lines 2 through 4

sed '/pattern/d' file Delete lines matching pattern

sed -i 's/foo/bar/g' file Edit file IN PLACE (modifies file)

sed '1s/^/header\n/' file Insert a header line

sed -n '/start/,/end/p' Print block between start and end patterns


■ Always test sed -i on a copy first. Use sed -[Link] to create backup automatically.

Unix & Shell Scripting — Complete Reference Page 10


6. Searching & Filtering
grep — Search Text
Command / Syntax Description & Notes

grep 'pattern' file Search for pattern in file

grep -i 'pattern' file Case-insensitive search

grep -r 'pattern' dir/ Recursive search in directory

grep -n 'pattern' file Show matching line numbers

grep -v 'pattern' file Invert match — lines NOT matching

grep -c 'pattern' file Count matching lines

grep -l 'pattern' *.txt List files containing pattern

grep -w 'word' file Match whole word only

grep -A3 'pattern' file Show 3 lines After match

grep -B3 'pattern' file Show 3 lines Before match

grep -E 'pat1|pat2' file Extended regex — match pat1 OR pat2

grep -P '\d+' file Perl-compatible regex (PCRE)

grep -o 'pattern' file Print only the matching part

find — Search for Files


Command / Syntax Description & Notes

find . -name '[Link]' Find by exact name from current dir

find . -name '*.py' Find all Python files

find . -iname '*.PY' Case-insensitive name match

find /home -type f Find regular files only

find /home -type d Find directories only

find . -size +10M Files larger than 10 MB

find . -size -1k Files smaller than 1 KB

find . -mtime -7 Modified within last 7 days

find . -mtime +30 Modified more than 30 days ago

find . -user alice Files owned by alice

find . -perm 644 Files with exact permissions 644

find . -name '*.log' -delete Find and delete matching files

find . -name '*.sh' -exec chmod +x {} \; Find & run command on each

find . -empty Find empty files and directories

find . -maxdepth 2 -name '*.c' Search at most 2 levels deep

Unix & Shell Scripting — Complete Reference Page 11


locate & updatedb
Command / Syntax Description & Notes

locate filename Fast search using database index

updatedb Update the locate database (run as root)

locate -i filename Case-insensitive locate


■ locate uses a pre-built database and is faster than find, but may be out of date. Run updatedb to refresh it.

Unix & Shell Scripting — Complete Reference Page 12


7. Networking Commands
Command / Syntax Description & Notes

ping [Link] Test network connectivity (Ctrl+C to stop)

ping -c 4 [Link] Send exactly 4 packets

traceroute [Link] Show packet route to host

nslookup [Link] DNS lookup — find IP of hostname

dig [Link] Detailed DNS query

dig @[Link] [Link] A Query specific DNS server for A record

host [Link] Simple DNS lookup

ip addr Show IP addresses and interfaces (modern)

ip route Show routing table

ifconfig Show network interfaces (older systems)

netstat -tuln List open ports and listening services

ss -tuln Modern replacement for netstat

curl [Link] Fetch URL content

curl -O [Link] Download file keeping original name

curl -L -o [Link] url Follow redirects, save as [Link]

curl -I url Fetch HTTP headers only

wget [Link] Download file (resumes with -c)

wget -r [Link] Mirror website recursively

scp file user@host:/path Secure copy to remote host

scp user@host:/file . Secure copy from remote to current dir

ssh user@hostname Connect to remote host via SSH

ssh -p 2222 user@host SSH on non-standard port

rsync -avz src/ user@h:dst/ Efficient sync to remote (archive, verbose, compress)

nc -zv host 80 Test if port 80 is open (netcat)

Unix & Shell Scripting — Complete Reference Page 13


8. Archiving & Compression
tar
Command / Syntax Description & Notes

tar -cvf [Link] dir/ Create tar archive of directory

tar -xvf [Link] Extract tar archive

tar -czvf [Link] dir/ Create gzip-compressed archive (.[Link])

tar -xzvf [Link] Extract gzip archive

tar -cjvf [Link].bz2 dir/ Create bzip2 archive

tar -xjvf [Link].bz2 Extract bzip2 archive

tar -tvf [Link] List contents without extracting

tar -xzvf [Link] -C /dest Extract to specific directory


■ tar flags: c=create x=extract v=verbose f=filename z=gzip j=bzip2 t=list

gzip, bzip2, xz, zip


Command / Syntax Description & Notes

gzip [Link] Compress → [Link] (replaces original)

gzip -d [Link] Decompress gzip file

gunzip [Link] Same as gzip -d

gzip -k [Link] Compress keeping original file

gzip -9 [Link] Maximum compression level

bzip2 [Link] Compress with bzip2 (better ratio than gzip)

bunzip2 [Link].bz2 Decompress bzip2 file

xz [Link] Compress with xz (best ratio, slowest)

unxz [Link] Decompress xz file

zip [Link] file1 file2 Create zip archive

zip -r [Link] dir/ Zip directory recursively

unzip [Link] Extract zip archive

unzip -l [Link] List zip contents

Unix & Shell Scripting — Complete Reference Page 14


9. Disk & System Monitoring
Command / Syntax Description & Notes

df -h Disk space usage of all filesystems (human-readable)

df -h /home Disk space for specific filesystem

du -sh dir/ Total size of directory

du -h --max-depth=1 / Size of each item in root (1 level)

du -sh * | sort -rh Sort directories by size

free -h RAM and swap usage

vmstat 1 Virtual memory stats every 1 second

iostat CPU and I/O statistics

uptime System uptime and load averages

uname -a All system info: kernel, hostname, arch

hostname Show system hostname

whoami Show current username

id Show UID, GID, and group memberships

who Show logged-in users

w Show users and what they are doing

last Show login history

history Show command history

!42 Repeat command number 42 from history

!! Repeat last command

date Show current date and time

date +"%Y-%m-%d" Format date as YYYY-MM-DD

cal Display calendar for current month

env Print all environment variables

export VAR=value Set and export an environment variable

echo $PATH Print the PATH variable

Unix & Shell Scripting — Complete Reference Page 15


10. Redirection, Pipes & Special Characters
Standard Streams
Command / Syntax Description & Notes

stdin (0) Standard input — keyboard by default

stdout (1) Standard output — screen by default

stderr (2) Standard error — screen by default

Redirection Operators
Command / Syntax Description & Notes

cmd > file Redirect stdout to file (overwrite)

cmd >> file Redirect stdout to file (append)

cmd < file Read stdin from file

cmd 2> [Link] Redirect stderr to file

cmd 2>&1 Redirect stderr to same destination as stdout

cmd > out 2>&1 Both stdout and stderr to file

cmd &> file Bash shorthand: stdout + stderr to file

cmd 2>/dev/null Discard stderr (suppress error messages)

cmd > /dev/null 2>&1 Discard ALL output

cmd << EOF Here-document — multi-line stdin until EOF

cmd <<< "string" Here-string — feed string as stdin

Pipes & Command Chaining


Command / Syntax Description & Notes

cmd1 | cmd2 Pipe stdout of cmd1 to stdin of cmd2

cmd1 | cmd2 | cmd3 Chain multiple commands

cmd1 && cmd2 Run cmd2 ONLY if cmd1 succeeds (exit 0)

cmd1 || cmd2 Run cmd2 ONLY if cmd1 fails

cmd1 ; cmd2 Run cmd2 regardless of cmd1 exit status

(cmd1 ; cmd2) Run in a subshell

cmd1 | tee file Pipe and also save output to file

cmd1 | xargs cmd2 Pass cmd1 output as arguments to cmd2

Special Characters & Globbing


Command / Syntax Description & Notes

* Wildcard — matches any string (including empty)

Unix & Shell Scripting — Complete Reference Page 16


? Matches any single character

[abc] Match a, b, or c

[a-z] Match any lowercase letter

{a,b,c} Brace expansion — a, b, or c

~ Home directory shortcut

$VAR Variable expansion

$(cmd) Command substitution — replace with output of cmd

`cmd` Older command substitution syntax (avoid)

\ Escape next character (remove special meaning)

' ' Single quotes — no expansion whatsoever

" " Double quotes — allows $ and ` expansion

# Comment — rest of line ignored

; Command separator

Practical Examples
• Count errors in log: grep -c 'ERROR' /var/log/[Link]
• Top 10 memory processes: ps aux | sort -k4 -rn | head -10
• Unique IPs in access log: awk '{print $1}' [Link] | sort | uniq -c | sort -rn
• Find & replace in all .conf files: find /etc -name '*.conf' | xargs sed -i 's/old/new/g'

Unix & Shell Scripting — Complete Reference Page 17


11. Shell Scripting — Introduction
A shell script is a text file containing a sequence of shell commands that are executed in order. Scripts automate
repetitive tasks, system administration, and complex workflows.

Shebang Line
The first line of every script should specify the interpreter using #! (shebang):
#!/bin/bash # Use bash interpreter
#!/usr/bin/env bash # Preferred: portable, finds bash in PATH
#!/bin/sh # POSIX sh (more portable, fewer features)

Creating and Running a Script


Command / Syntax Description & Notes

nano [Link] Create script file in nano editor

chmod +x [Link] Make script executable

./[Link] Execute script from current directory

bash [Link] Run with bash explicitly (no +x needed)

bash -x [Link] Debug mode — print each command before executing

bash -n [Link] Syntax check only (no execution)

source [Link] Run in CURRENT shell (variables persist after)

. [Link] Same as source (POSIX)

Minimal Hello World Script


#!/usr/bin/env bash
# This is a comment
echo "Hello, World!"
echo "Current date: $(date)"
echo "Logged in as: $USER"

Script Exit Codes


Every command returns an exit code: 0 = success, non-zero = failure. Use $? to read the last exit code.
ls /nonexistent
echo "Exit code: $?" # prints: Exit code: 2
exit 0 # explicitly exit with success
exit 1 # exit with error

Unix & Shell Scripting — Complete Reference Page 18


12. Variables & Data Types
Bash is dynamically typed — variables are untyped by default (everything is a string). Types are determined by
context. Use declare for explicit types.

Variable Basics
name="Alice" # No spaces around =
age=25
echo $name # Alice
echo ${name} # Alice (braces recommended for clarity)
echo "Hello, $name" # Hello, Alice
echo 'Hello, $name' # Hello, \$name (no expansion in single quotes)

Data Types with declare


Command / Syntax Description & Notes

declare -i num=10 Integer — arithmetic errors enforced

declare -r PI=3.14 Read-only (constant) — cannot be changed

declare -l lower Lowercase — converts value to lowercase

declare -u upper Uppercase — converts value to uppercase

declare -a arr Indexed array (see Chapter 18)

declare -A assoc Associative array (hash/dict)

declare -x VAR=val Export variable to child processes

declare -p VAR Print variable attributes and value

Environment Variables
Environment variables are available to all child processes. Set with export.
export MYVAR='hello' # Export to child processes
export PATH=$PATH:/new/dir # Append to PATH
unset MYVAR # Delete variable
readonly CONST=42 # Declare read-only

Built-in Special Variables


Command / Syntax Description & Notes

$0 Name of the script

$1 - $9 Positional parameters — script arguments

${10} 10th argument (braces required for 2+ digits)

$# Number of arguments passed to script

$@ All arguments as separate quoted strings

$* All arguments as a single string

$? Exit status of last command

Unix & Shell Scripting — Complete Reference Page 19


$$ PID of current shell

$! PID of last background process

$- Current shell options flags

$_ Last argument of previous command

$RANDOM Random integer between 0 and 32767

$LINENO Current line number in the script

$BASH_VERSION Version of bash running

$HOME Home directory

$USER Current username

$HOSTNAME System hostname

$PWD Current working directory

$OLDPWD Previous working directory

$IFS Internal Field Separator (default: space tab newline)

$PATH Colon-separated list of command search directories

$SHELL Path to current shell

$TERM Terminal type

$EDITOR Default editor

$LANG Language/locale setting

Command Substitution
today=$(date +%Y-%m-%d) # Capture command output
files=$(ls *.txt)
lines=$(wc -l < [Link])
echo "There are $lines lines"

Arithmetic
a=5; b=3
echo $((a + b)) # 8
echo $((a * b)) # 15
echo $((a ** b)) # 125 (power)
echo $((a / b)) # 1 (integer division)
echo $((a % b)) # 2 (modulo)
((count++)) # Increment
((count--)) # Decrement
let result=a*b+2 # let for arithmetic
result=$(echo '3.14*2' | bc -l) # Float: use bc
■ Bash only does integer arithmetic natively. For floats, use bc or awk.

Unix & Shell Scripting — Complete Reference Page 20


13. Operators
String Comparison Operators (inside [ ] or [[ ]])
Command / Syntax Description & Notes

[ "$a" = "$b" ] Equal (POSIX, use = not ==)

[ "$a" == "$b" ] Equal (bash, same as =)

[ "$a" != "$b" ] Not equal

[ -z "$a" ] True if string is empty (zero length)

[ -n "$a" ] True if string is NOT empty

[[ $a < $b ]] Lexicographic less-than (use [[ ]])

[[ $a > $b ]] Lexicographic greater-than

[[ $a =~ regex ]] Regex match (bash only, [[ ]] required)

Integer Comparison Operators


Command / Syntax Description & Notes

[ $a -eq $b ] Equal

[ $a -ne $b ] Not equal

[ $a -lt $b ] Less than

[ $a -le $b ] Less than or equal

[ $a -gt $b ] Greater than

[ $a -ge $b ] Greater than or equal

File Test Operators


Command / Syntax Description & Notes

[ -e file ] File exists (any type)

[ -f file ] Exists and is a regular file

[ -d file ] Exists and is a directory

[ -L file ] Exists and is a symbolic link

[ -r file ] File is readable

[ -w file ] File is writable

[ -x file ] File is executable

[ -s file ] File exists and is NOT empty (size > 0)

[ -z file ] File is empty (zero size)

[ f1 -nt f2 ] f1 is newer than f2

[ f1 -ot f2 ] f1 is older than f2

Unix & Shell Scripting — Complete Reference Page 21


[ f1 -ef f2 ] f1 and f2 are the same file (hard link)

Logical Operators
Command / Syntax Description & Notes

[ cond1 ] && [ cond2 ] AND — both must be true

[ cond1 ] || [ cond2 ] OR — at least one true

[ ! condition ] NOT — negate condition

[[ cond1 && cond2 ]] AND inside [[ ]] (preferred in bash)

[[ cond1 || cond2 ]] OR inside [[ ]]

-a inside [ ] AND (POSIX, inside single [ ])

-o inside [ ] OR (POSIX, inside single [ ])


■ Use [[ ]] (double brackets) in bash scripts — safer, supports regex, no word splitting.

Unix & Shell Scripting — Complete Reference Page 22


14. Control Flow — if / elif / else
Basic if Syntax
if [ condition ]; then
# commands if condition is true
fi

if / else
if [ condition ]; then
echo "True"
else
echo "False"
fi

if / elif / else
if [ condition1 ]; then
echo "Condition 1 met"
elif [ condition2 ]; then
echo "Condition 2 met"
elif [ condition3 ]; then
echo "Condition 3 met"
else
echo "No condition met"
fi

Practical Examples
Example 1 — Check if file exists
#!/usr/bin/env bash
file="/etc/passwd"
if [ -f "$file" ]; then
echo "File exists: $file"
else
echo "File not found: $file"
fi

Example 2 — Compare numbers


#!/usr/bin/env bash
read -p "Enter a number: " num
if [ "$num" -lt 0 ]; then
echo "Negative"
elif [ "$num" -eq 0 ]; then
echo "Zero"
elif [ "$num" -le 100 ]; then
echo "Between 1 and 100"

Unix & Shell Scripting — Complete Reference Page 23


else
echo "Greater than 100"
fi

Example 3 — Check user input


#!/usr/bin/env bash
read -p "Enter username: " user
if [ -z "$user" ]; then
echo "Error: username cannot be empty"
exit 1
fi
echo "Welcome, $user!"

Example 4 — Using [[ ]] with regex


#!/usr/bin/env bash
read -p "Enter email: " email
if [[ "$email" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
echo "Valid email"
else
echo "Invalid email format"
fi

Example 5 — Short-circuit (one-liner)


[ -d "/backup" ] || mkdir /backup # Create dir if missing
[ -f "[Link]" ] && source [Link] # Source if exists
■ [[ ]] is preferred over [ ] in bash. Always quote variables: "$var" to prevent word splitting.

Unix & Shell Scripting — Complete Reference Page 24


15. Loops — for, while, until
for Loop — List Iteration
for item in item1 item2 item3; do
echo "$item"
done

for Loop — C-style


for ((i=1; i<=10; i++)); do
echo "Number: $i"
done

for Loop — Range with seq or brace expansion


for i in {1..10}; do echo $i; done # 1 to 10
for i in {0..20..5}; do echo $i; done # 0 5 10 15 20
for i in $(seq 1 2 10); do echo $i; done # 1 3 5 7 9

for Loop — Files & Command Output


for file in *.txt; do
echo "Processing: $file"
wc -l "$file"
done

for user in $(cat /etc/passwd | cut -d: -f1); do


echo "User: $user"
done

while Loop
while [ condition ]; do
# commands
done

Example — Count down


count=5
while [ $count -gt 0 ]; do
echo "Countdown: $count"
((count--))
done
echo "Liftoff!"

Example — Read file line by line


while IFS= read -r line; do
echo "Line: $line"
done < [Link]

Unix & Shell Scripting — Complete Reference Page 25


Example — Infinite loop with break
while true; do
read -p "Enter 'quit' to exit: " input
if [ "$input" = "quit" ]; then
break
fi
echo "You entered: $input"
done

until Loop
Runs while the condition is FALSE — opposite of while.
count=0
until [ $count -ge 5 ]; do
echo "count is $count"
((count++))
done

Loop Control
Command / Syntax Description & Notes

break Exit the loop immediately

break 2 Exit 2 levels of nested loops

continue Skip to next iteration

continue 2 Skip to next iteration of outer loop

Example — break and continue


for i in {1..10}; do
if [ $i -eq 5 ]; then continue; fi # skip 5
if [ $i -eq 8 ]; then break; fi # stop at 8
echo $i
done
# Output: 1 2 3 4 6 7
■ Always quote variables in loop conditions: [ "$var" = "value" ] not [ $var = value ]

Unix & Shell Scripting — Complete Reference Page 26


16. case Statement
The case statement is a multi-branch conditional — cleaner than many elif chains when testing a variable
against multiple patterns.

Syntax
case $variable in
pattern1)
# commands
;;
pattern2 | pattern3) # OR patterns
# commands
;;
*) # Default (wildcard)
# commands
;;
esac

Example 1 — Day of the week


#!/usr/bin/env bash
day=$(date +%A)
case $day in
Monday|Tuesday|Wednesday|Thursday|Friday)
echo "Weekday: $day"
;;
Saturday|Sunday)
echo "Weekend: $day"
;;
*)
echo "Unknown day"
;;
esac

Example 2 — Simple menu


#!/usr/bin/env bash
echo "1) Start service"
echo "2) Stop service"
echo "3) Restart service"
read -p "Choose [1-3]: " choice

case $choice in
1) echo "Starting..." ;;
2) echo "Stopping..." ;;
3) echo "Restarting..." ;;
*) echo "Invalid option" ; exit 1 ;;

Unix & Shell Scripting — Complete Reference Page 27


esac

Example 3 — File extension handler


#!/usr/bin/env bash
file="$1"
case ${file##*.} in # Extract extension
txt|md) echo "Text file" ;;
sh|bash) echo "Shell script" ;;
py) echo "Python script" ;;
jpg|png|gif) echo "Image file" ;;
*) echo "Unknown type" ;;
esac
■ Patterns support wildcards: * ? [abc]. Use | to match multiple patterns in one branch.

Unix & Shell Scripting — Complete Reference Page 28


17. Functions
Defining & Calling Functions
# Method 1 (preferred)
function greet() {
echo "Hello, $1!"
}

# Method 2 (POSIX compatible)


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

greet "Alice" # Call the function

Parameters & Return Values


Functions receive arguments via $1, $2 … $n. Return values: use return N for exit code (0–255), or echo to
return strings.
add() {
local result=$(( $1 + $2 )) # local scope
echo $result # 'return' a string
}

sum=$(add 4 7) # Capture output


echo "Sum = $sum" # Sum = 11

local Variables
Variables inside functions are global by default. Use local to restrict scope.
counter=10
increment() {
local counter=0 # local copy
((counter++))
echo "Inside: $counter" # 1
}

increment
echo "Outside: $counter" # Still 10

Comprehensive Example
#!/usr/bin/env bash

# ■■ Logging helpers ■■■■■■■■■■■■■■■■■■■■■■


log_info() { echo "[INFO] $*"; }
log_error() { echo "[ERROR] $*" >&2; }

# ■■ Validate arguments ■■■■■■■■■■■■■■■■■■■


check_args() {
if [ $# -lt 2 ]; then

Unix & Shell Scripting — Complete Reference Page 29


log_error "Usage: $0 <src> <dst>"
return 1
fi
return 0
}

# ■■ Backup file ■■■■■■■■■■■■■■■■■■■■■■■■■■


backup_file() {
local src="$1"
local dst="$2"
if [ ! -f "$src" ]; then
log_error "Source not found: $src"
return 1
fi
cp -p "$src" "$dst" && log_info "Backed up to $dst"
}

# ■■ Main ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
check_args "$@" || exit 1
backup_file "$1" "$2"
■ Always use 'local' for variables inside functions to avoid polluting global scope.

Unix & Shell Scripting — Complete Reference Page 30


18. Arrays
Indexed Arrays
# Declare and initialize
fruits=("apple" "banana" "cherry")
nums=(1 2 3 4 5)

# Access elements (0-indexed)


echo ${fruits[0]} # apple
echo ${fruits[2]} # cherry
echo ${fruits[-1]} # cherry (last element, bash 4+)

# All elements
echo ${fruits[@]} # apple banana cherry
echo ${fruits[*]} # apple banana cherry

# Array length
echo ${#fruits[@]} # 3

# Modify element
fruits[1]="blueberry"

# Append element
fruits+=("date")

# Slice: elements 1 and 2 (offset 1, length 2)


echo ${fruits[@]:1:2}

# Delete element
unset fruits[2]

# Iterate
for fruit in "${fruits[@]}"; do
echo "Fruit: $fruit"
done
# Iterate with index
for i in "${!fruits[@]}"; do
echo "$i: ${fruits[$i]}"
done

Associative Arrays (Key-Value / Hash Maps) — bash 4+


declare -A person
person[name]="Alice"
person[age]=30
person[city]="Nairobi"

# Or initialize all at once


declare -A config=([host]="localhost" [port]="8080")

echo ${person[name]} # Alice


echo ${person[age]} # 30

# All keys
echo ${!person[@]} # name age city

Unix & Shell Scripting — Complete Reference Page 31


# All values
echo ${person[@]}

# Iterate key-value
for key in "${!person[@]}"; do
echo "$key = ${person[$key]}"
done

# Delete a key
unset person[city]

# Check if key exists


if [[ -v person[name] ]]; then
echo "name key exists"
fi
■ Associative arrays require bash version 4+. Check with: bash --version

Unix & Shell Scripting — Complete Reference Page 32


19. String Manipulation
Bash provides powerful built-in parameter expansion for strings, avoiding the need for external tools.

String Length & Slicing


str="Hello, World!"
echo ${#str} # Length: 13
echo ${str:7} # Slice from index 7: World!
echo ${str:7:5} # Slice 5 chars from 7: World
echo ${str: -6} # Last 6 chars: orld!

Substitution
path="/usr/local/bin/bash"
echo ${path/bash/sh} # Replace first 'bash' with 'sh'
echo ${path//i/I} # Replace ALL 'i' with 'I'
echo ${path/#\/usr/\/opt} # Replace prefix /usr with /opt
echo ${path/%bash/dash} # Replace suffix bash with dash

Prefix & Suffix Removal


filename="backup_2024-[Link]"

# Remove prefix (shortest match)


echo ${filename#*_} # [Link]

# Remove prefix (longest match)


echo ${filename##*/} # backup_2024-[Link]

# Remove suffix (shortest)


echo ${filename%.*} # backup_2024-[Link]
# Remove suffix (longest)
echo ${filename%%.*} # backup_2024-01-15

# Practical: extract extension


ext=${filename##*.} # gz

# Practical: strip extension


base=${filename%.[Link]} # backup_2024-01-15

Case Conversion (bash 4+)


name="hello world"
echo ${name^} # Hello world (first char upper)
echo ${name^^} # HELLO WORLD (all upper)
name2="HELLO WORLD"
echo ${name2,} # hELLO WORLD (first char lower)
echo ${name2,,} # hello world (all lower)

Default & Alternate Values

Unix & Shell Scripting — Complete Reference Page 33


Command / Syntax Description & Notes

${var:-default} Use default if var is unset or empty

${var:=default} Assign default if var is unset or empty

${var:+alternate} Use alternate if var IS set and non-empty

${var:?message} Print message and exit if var is unset

${var:-} Empty string if var is unset (no error)


# Examples
echo ${name:-"Anonymous"} # Anonymous if name is empty
echo ${port:=8080} # Sets port=8080 if unset
echo ${DEBUG:+"[DEBUG]"} # Prints [DEBUG] only if DEBUG is set

Unix & Shell Scripting — Complete Reference Page 34


20. File I/O in Scripts
Writing to Files
# Overwrite
echo "Hello" > [Link]

# Append
echo "World" >> [Link]

# Write multiple lines (heredoc)


cat > [Link] << EOF
host=localhost
port=8080
debug=false
EOF

# Write with printf (precise formatting)


printf "%s\n" "Line 1" "Line 2" "Line 3" > [Link]

Reading from Files


# Read entire file into variable
content=$(cat [Link])

# Read line by line (correct way)


while IFS= read -r line; do
echo ">> $line"
done < [Link]

# Read with filename as variable


input_file="[Link]"
while IFS=',' read -r col1 col2 col3; do
echo "Name: $col1 Age: $col2 City: $col3"
done < "$input_file"

# Read first line


read -r first_line < [Link]
echo "First line: $first_line"

# Read all lines into array


mapfile -t lines < [Link]
echo "Total lines: ${#lines[@]}"
echo "Line 3: ${lines[2]}"

File Checks Before I/O


#!/usr/bin/env bash
input="/path/to/[Link]"
output="/path/to/[Link]"

# Check input exists and is readable


if [ ! -f "$input" ]; then
echo "Error: $input not found" >&2

Unix & Shell Scripting — Complete Reference Page 35


exit 1
fi

if [ ! -r "$input" ]; then
echo "Error: $input not readable" >&2
exit 1
fi

# Process
while IFS= read -r line; do
echo "${line^^}" # uppercase
done < "$input" > "$output"

echo "Done. Output saved to $output"


■ IFS= (empty IFS) and -r (raw mode) prevent stripping of leading/trailing spaces and backslash processing.

Unix & Shell Scripting — Complete Reference Page 36


21. Error Handling & Debugging
set Options for Safety
Command / Syntax Description & Notes

set -e Exit immediately if any command fails (errexit)

set -u Treat unset variables as errors (nounset)

set -o pipefail Pipe fails if ANY command in the pipe fails

set -x Print each command before executing (xtrace/debug)

set -v Print each line of script as it is read

set +e Turn off -e (temporarily allow failures)

set +x Turn off debugging

set -euo pipefail The professional default — use at top of scripts


#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t' # Safer IFS

Trapping Errors & Signals


# Run cleanup on exit (always)
cleanup() {
echo "Cleaning up..."
rm -f /tmp/myscript_$$
}
trap cleanup EXIT

# Catch errors
trap 'echo "Error on line $LINENO"' ERR

# Handle Ctrl+C
trap 'echo "Interrupted!"; exit 1' INT

# Multiple signals
trap cleanup EXIT ERR INT TERM

Custom Error Handling


die() {
local msg="$1"
local code="${2:-1}" # Default exit code 1
echo "[ERROR] $msg" >&2
exit "$code"
}

[ -f "$config" ] || die "Config file not found: $config" 2

Debugging Techniques

Unix & Shell Scripting — Complete Reference Page 37


Command / Syntax Description & Notes

bash -x [Link] Debug entire script — shows each command

bash -n [Link] Syntax check without running

bash -v [Link] Verbose — print script as it reads

set -x … set +x Enable/disable debug for a section

echo "VAR=$VAR" >&2 Print debug info to stderr

PS4='+ ${BASH_SOURCE}:${LINENO}: ' Show file and line in debug output


# Inline debug section
set -x
suspicious_command "$arg"
set +x
■ Always write error messages to stderr: echo 'Error' >&2 so they can be separated from stdout.

Unix & Shell Scripting — Complete Reference Page 38


22. Regular Expressions
Regular expressions (regex) are patterns used to match text. Bash uses them in [[ =~ ]], grep, sed, and awk.

Basic Regex Metacharacters


Command / Syntax Description & Notes

. Match any single character (except newline)

* 0 or more of preceding element

+ 1 or more of preceding element (ERE)

? 0 or 1 of preceding element (ERE)

^ Start of line

$ End of line

[abc] Character class — matches a, b, or c

[^abc] Negated class — matches anything except a, b, c

[a-z] Range — any lowercase letter

\d Digit (Perl/PCRE: use [0-9] in POSIX)

\w Word character [a-zA-Z0-9_]

\s Whitespace (space, tab, newline)

\b Word boundary

{n} Exactly n occurrences

{n,m} Between n and m occurrences

(abc) Group — treat as unit

a|b Alternation — a OR b (ERE)

\ Escape metacharacter

Common Regex Patterns


Command / Syntax Description & Notes

^[0-9]+$ Integer (digits only)

^-?[0-9]+(\.[0-9]+)?$ Number (optional decimal)

Email address
[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}

^(https?|ftp)://[^\s/$.?#].[^\s]*$ URL

^[0-9]{1,3}(\.[0-9]{1,3}){3}$ IPv4 address

^[0-9]{4}-[0-9]{2}-[0-9]{2}$ Date YYYY-MM-DD

^[A-Z][a-z]+$ Capitalized word

#[0-9a-fA-F]{6} Hex colour code

Unix & Shell Scripting — Complete Reference Page 39


Using Regex in Bash
# In [[ ]] (POSIX ERE, no quotes around pattern)
if [[ "$email" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
echo "Valid email"
fi

# Capture groups — stored in ${BASH_REMATCH[@]}


[[ "2024-01-15" =~ ^([0-9]{4})-([0-9]{2})-([0-9]{2})$ ]]
echo "Year: ${BASH_REMATCH[1]}" # 2024
echo "Month: ${BASH_REMATCH[2]}" # 01
echo "Day: ${BASH_REMATCH[3]}" # 15

# grep with ERE


grep -E '^[0-9]{3}-[0-9]{4}$' [Link]

# sed with regex


sed -E 's/[0-9]{4}/YEAR/g' [Link]

# awk with regex


awk '/^[A-Z]/' [Link] # Lines starting with uppercase

Unix & Shell Scripting — Complete Reference Page 40


23. Advanced Topics & Best Practices
User Input with read
read -p "Enter name: " name
read -s -p "Password: " pass # -s: silent (no echo)
read -t 10 -p "Answer (10s): " ans # -t: timeout
read -n 1 -p "Press a key: " key # -n: read N chars
read -a arr -p "Enter words: " # read into array

select — Interactive Menus


PS3="Choose an option: "
select option in "Start" "Stop" "Restart" "Quit"; do
case $option in
Start) echo "Starting..." ;;
Stop) echo "Stopping..." ;;
Restart) echo "Restarting..." ;;
Quit) break ;;
*) echo "Invalid" ;;
esac
done

Process Substitution
# Use command output as a file
diff <(sort [Link]) <(sort [Link])
while read line; do echo $line; done < <(ls -la)

Here Documents & Here Strings


# Heredoc — multi-line text as stdin
cat << EOF
Line 1
Line 2
EOF

# Heredoc with variable expansion suppressed


cat << 'EOF'
No \$expansion here
EOF

# Here string — single string as stdin


grep 'hello' <<< "hello world"

Script Arguments with getopts


#!/usr/bin/env bash
usage() { echo "Usage: $0 [-v] [-f file] [-n name]"; exit 1; }

verbose=false; file=""; name=""

Unix & Shell Scripting — Complete Reference Page 41


while getopts ":vf:n:h" opt; do
case $opt in
v) verbose=true ;;
f) file="$OPTARG" ;;
n) name="$OPTARG" ;;
h) usage ;;
:) echo "Option -$OPTARG requires argument"; usage ;;
?) echo "Unknown option: -$OPTARG"; usage ;;
esac
done
shift $((OPTIND - 1)) # Remove parsed options, $@ = remaining args

Subshells & Command Groups


# Subshell — changes don't affect parent
(cd /tmp && ls) # cd only affects subshell
echo $PWD # original dir unchanged

# Command group — runs in current shell


{ echo "line1"; echo "line2"; } > [Link]

eval & exec


# eval — execute string as command (use carefully)
cmd="ls -la"
eval "$cmd"

# exec — replace current shell with command (no return)


exec /usr/bin/python3 [Link]

Best Practices Summary


• Always start with: #!/usr/bin/env bash and set -euo pipefail
• Quote variables: Use "$var" not $var to prevent word splitting
• Use [[ ]] not [ ] in bash for safer string comparisons
• Local variables in functions: declare local to avoid side effects
• Use $() not backticks for command substitution — easier to nest
• Check exit codes: test commands and handle failures gracefully
• Write to stderr: echo 'error' >&2 for error/debug messages
• Use meaningful names: max_retries not mr; log_error() not le()
• Add usage() function: describe flags and arguments clearly
• Trap EXIT: always clean up temp files with trap cleanup EXIT
• Avoid eval: it executes arbitrary code — use arrays instead
• Test on /bin/sh too: if POSIX portability matters

Commonly Used One-Liners


Command / Syntax Description & Notes

Batch
for f in *.jpg; do convert $f ${f%.jpg}.png; convert images
done

Unix & Shell Scripting — Complete Reference Page 42


Count all Python lines
find . -name '*.py' | xargs wc -l | tail -1

Top|10
history | awk '{print $2}' | sort | uniq -c commands
sort -rn |used
head

Diff remote
diff <(ssh host1 cat /etc/hosts) <(ssh host2 files
cat /etc/hosts)

watch -n 2 df -h Monitor disk every 2s

while sleep 1; do clear; df -h; done Refresh disk info loop

python3 -m [Link] 8080 Instant HTTP file server

nc -l 9999 | bash Simple remote shell (careful!)

End of Unix & Shell Scripting Complete Reference Guide

Unix & Shell Scripting — Complete Reference Page 43

You might also like