Shell Scripting Cheat Sheet β€” Bash, Variables, Loops, Pipes, Cron | Dataplexa

Shell Scripting

bash  Β·  variables  Β·  loops  Β·  functions  Β·  pipes  Β·  redirection  Β·  grep  Β·  sed  Β·  awk  Β·  cron

Sheet 3 of 3 Bash 5.x Beginner Printable

Script Basics & Variables

shebang Β· declare Β· $VAR Β· special vars
Shebang & Running Scripts
#!/bin/bash
# ↑ shebang β€” which interpreter to use
# Also common: #!/usr/bin/env bash

# Make script executable
chmod +x script.sh

# Run it
./script.sh
bash script.sh   # or explicitly

# Print to terminal
echo "Hello, World!"
printf "%s is %d years old\n" "Alice" 25

# Comments
# This is a single-line comment
Variables & Quoting
# Assign (no spaces around =)
NAME="Alice"
AGE=25
GREETING="Hello"

# Read variable (use $)
echo "$NAME"              # Alice
echo "${NAME}"            # Alice (safer)
echo "$GREETING, $NAME!"  # Hello, Alice!

# readonly β€” cannot be changed
readonly PI=3.14159

# unset β€” delete variable
unset AGE

# Single quotes β€” no interpolation
echo '$NAME'             # $NAME (literal)

# Command substitution
TODAY=$(date +%Y-%m-%d)
FILES=$(ls -1 | wc -l)
Special Variables
# Script arguments
$0   # script name
$1   # first argument
$2   # second argument
$@   # all arguments (array)
$#   # number of arguments

# Process & status
$$   # current PID
$!   # PID of last background job
$?   # exit code of last command
     # 0 = success, non-zero = error

# Usage example
#!/bin/bash
echo "Script: $0"
echo "First arg: $1"
echo "All args: $@"
echo "Count: $#"

# Environment variables
echo $HOME     # /home/user
echo $USER     # username
echo $PATH     # executable search path
echo $PWD      # current directory
Always quote variables: Use "$VAR" not $VAR to prevent word splitting and glob expansion when the value contains spaces or special characters.

Conditionals

if Β· test Β· [[ ]] Β· case
if / elif / else
AGE=20

if [[ $AGE -ge 18 ]]; then
  echo "Adult"
elif [[ $AGE -ge 13 ]]; then
  echo "Teen"
else
  echo "Child"
fi

# Numeric comparisons
# -eq  equal
# -ne  not equal
# -lt  less than
# -le  less than or equal
# -gt  greater than
# -ge  greater than or equal

# String comparisons
[[ $A == $B ]]   # equal
[[ $A != $B ]]   # not equal
[[ -z $A ]]     # empty string
[[ -n $A ]]     # non-empty string
File Tests & case
# File test operators
[[ -f "file.txt" ]]  # is a regular file
[[ -d "/tmp"     ]]  # is a directory
[[ -e "path"    ]]  # exists
[[ -r "file"    ]]  # readable
[[ -w "file"    ]]  # writable
[[ -x "file"    ]]  # executable
[[ -s "file"    ]]  # not empty (size>0)

# Logical operators
[[ $A == 1 && $B == 2 ]]
[[ $A == 1 || $B == 2 ]]
[[ ! -f "file" ]]      # NOT

# case statement
case $DAY in
  Mon|Tue|Wed|Thu|Fri)
    echo "Weekday" ;;
  Sat|Sun)
    echo "Weekend" ;;
  *)
    echo "Unknown" ;;
esac

Loops

for Β· while Β· until Β· break Β· continue
for loops
# for-in β€” iterate list
for fruit in apple mango cherry; do
  echo "$fruit"
done

# C-style for loop
for ((i=0; i<5; i++)); do
  echo "$i"
done

# Range with brace expansion
for i in {1..5}; do
  echo "$i"
done

# Iterate files
for file in *.txt; do
  echo "Processing: $file"
done

# Iterate command output
for user in $(cat users.txt); do
  echo "Hello $user"
done
while Β· until Β· break Β· continue
# while β€” loop while true
COUNT=1
while [[ $COUNT -le 5 ]]; do
  echo "Count: $COUNT"
  ((COUNT++))
done

# Read file line by line
while IFS= read -r line; do
  echo "$line"
done < file.txt

# until β€” loop while false
until [[ $COUNT -gt 5 ]]; do
  ((COUNT++))
done

# break and continue
for i in {1..10}; do
  [[ $i -eq 3 ]] && continue  # skip 3
  [[ $i -eq 7 ]] && break     # stop at 7
  echo $i
done

Functions

define Β· arguments Β· return Β· local Β· scope
Define & Call
# Function definition
greet() {
  echo "Hello, $1!"
}

# Alternative syntax
function say_bye {
  echo "Goodbye, $1!"
}

# Call a function
greet "Alice"    # Hello, Alice!
say_bye "Bob"  # Goodbye, Bob!

# Function must be defined before use
# Arguments: $1, $2, $@, $#
Return Values & Local Variables
# Return exit code (0=ok, 1=error)
is_even() {
  [[ $(($1 % 2)) -eq 0 ]]
}

if is_even 4; then
  echo "even"
fi

# Return a value via echo
add() {
  echo $(($1 + $2))
}
RESULT=$(add 3 5)
echo $RESULT   # 8

# local β€” function-scoped variable
my_func() {
  local TMP="only inside"
  echo $TMP
}
Useful Patterns
# Validate argument count
require_args() {
  if [[ $# -lt 2 ]]; then
    echo "Usage: $0 <a> <b>" >&2
    return 1
  fi
}

# Default parameter value
connect() {
  local HOST=${1:-"localhost"}
  local PORT=${2:-8080}
  echo "Connecting $HOST:$PORT"
}
connect             # localhost:8080
connect myserver    # myserver:8080
connect db 5432    # db:5432

Pipes & Redirection

| Β· > Β· >> Β· < Β· 2> Β· tee Β· xargs
Redirection
# stdout β†’ file (overwrite)
echo "Hello" > output.txt

# stdout β†’ file (append)
echo "World" >> output.txt

# stdin ← file
sort < names.txt

# stderr β†’ file
ls /bad/path 2> errors.log

# stdout + stderr β†’ file
command > all.log 2>&1
command &> all.log   # shorthand

# Discard output
command > /dev/null 2>&1

# Here document
cat <<EOF
Line 1
Line 2
EOF
Pipes & xargs
# | pipes stdout of one β†’ stdin of next
ls -la | grep ".txt"
cat file.txt | sort | uniq
ps aux | grep nginx

# tee β€” pipe AND write to file
ls -la | tee files.log

# xargs β€” pipe list β†’ command args
find . -name "*.log" | xargs rm
cat urls.txt | xargs curl -O

# Chain commands
mkdir newdir && cd newdir  # run if prev ok
cd /bad || echo "failed"   # run if prev fails
cmd1 ; cmd2               # run always

Arrays & Arithmetic

array Β· (( )) Β· $(( )) Β· string ops
Arrays
# Create array
FRUITS=("apple" "mango" "cherry")

# Access
echo ${FRUITS[0]}     # apple
echo ${FRUITS[@]}     # all elements
echo ${#FRUITS[@]}    # count = 3

# Modify
FRUITS+=("kiwi")      # append
FRUITS[1]="banana"   # replace index 1
unset FRUITS[2]       # remove index 2

# Loop over array
for f in "${FRUITS[@]}"; do
  echo $f
done
Arithmetic & String Operations
# Arithmetic
A=10; B=3
echo $((A + B))    # 13
echo $((A - B))    # 7
echo $((A * B))    # 30
echo $((A / B))    # 3 (integer)
echo $((A % B))    # 1
((A++))           # increment

# String operations
S="Hello World"
echo ${#S}          # length = 11
echo ${S:0:5}       # Hello (substr)
echo ${S,,}         # hello world (lower)
echo ${S^^}         # HELLO WORLD (upper)
echo ${S/World/Bash} # Hello Bash
echo ${S#Hello }    # World (strip prefix)

grep Β· sed Β· awk

search Β· transform Β· extract
grep β€” search text
# Basic search
grep "error" app.log

# Common flags
grep -i "error" app.log  # case insensitive
grep -n "error" app.log  # show line numbers
grep -c "error" app.log  # count matches
grep -v "debug" app.log  # invert (exclude)
grep -r "TODO" ./src/    # recursive
grep -l "error" *.log   # filenames only
grep -A2 "error" app.log # 2 lines after
grep -B2 "error" app.log # 2 lines before

# Extended regex (egrep)
grep -E "error|warn" app.log
grep -E "^[0-9]{4}" dates.txt

# Fixed string (faster, no regex)
grep -F "[ERROR]" app.log
sed β€” stream editor
# Substitute (replace)
sed 's/old/new/' file.txt     # first only
sed 's/old/new/g' file.txt    # global
sed 's/old/new/gi' file.txt   # case-insensitive

# Edit in-place
sed -i 's/foo/bar/g' file.txt
sed -i.bak 's/foo/bar/g' file.txt # backup

# Delete lines
sed '/pattern/d' file.txt   # matching lines
sed '2d' file.txt           # line 2
sed '2,5d' file.txt         # lines 2-5

# Print specific lines
sed -n '5p' file.txt         # line 5 only
sed -n '5,10p' file.txt      # lines 5-10

# Insert / Append
sed '2i\Inserted line' file.txt  # before line 2
sed '2a\Appended line' file.txt  # after line 2
awk β€” column & pattern processing
# Print specific column
awk '{print $1}' file.txt   # col 1
awk '{print $2, $4}' file.txt

# Custom delimiter
awk -F: '{print $1}' /etc/passwd
awk -F, '{print $1}' data.csv

# Pattern matching
awk '/error/{print}' app.log
awk '$3 > 100' data.txt     # col 3 > 100

# Built-in variables
# NR = line number
# NF = number of fields
awk '{print NR, $0}' file.txt  # add line nums
awk '{print $NF}' file.txt     # last column

# Sum a column
awk '{sum += $2} END {print sum}' data.txt

# BEGIN / END blocks
awk 'BEGIN{print "Start"} {print} END{print "End"}' f
Quick pipeline recipe: grep "ERROR" app.log | awk '{print $1, $4}' | sort | uniq -c | sort -rn | head -10 β€” find the top 10 most frequent errors with timestamps.

Cron Jobs

crontab Β· schedule Β· @reboot Β· @daily
Crontab syntax
# Edit crontab
crontab -e    # edit current user's crons
crontab -l    # list current crons
crontab -r    # remove all crons

# Format: min hr dom mon dow command
# β”Œβ”€β”€ minute       (0-59)
# β”‚ β”Œβ”€β”€ hour         (0-23)
# β”‚ β”‚ β”Œβ”€β”€ day of month (1-31)
# β”‚ β”‚ β”‚ β”Œβ”€β”€ month       (1-12)
# β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€ day of week (0-7, 0&7=Sun)
# β”‚ β”‚ β”‚ β”‚ β”‚
# * * * * *  command

# Examples
0  9 * * 1  /backup.sh   # 9am every Monday
30 2 * * *  /cleanup.sh  # 2:30am every day
*  * * * *  /script.sh   # every minute
0  0 1 * *  /monthly.sh  # midnight, 1st of month
0  * * * *  /hourly.sh   # every hour
0  0 * * 0  /weekly.sh   # midnight every Sunday
Shortcuts & Best Practices
# Special strings
@reboot   /start.sh    # on system boot
@hourly   /hourly.sh   # = 0 * * * *
@daily    /daily.sh    # = 0 0 * * *
@weekly   /weekly.sh   # = 0 0 * * 0
@monthly  /monthly.sh  # = 0 0 1 * *
@yearly   /yearly.sh   # = 0 0 1 1 *

# Ranges and steps
0 9-17 * * *   /cmd.sh   # every hr 9-17
*/15 * * * *  /cmd.sh   # every 15 mins
0 0 * * 1,3,5 /cmd.sh  # Mon,Wed,Fri

# Log output
0 2 * * * /backup.sh >> /var/log/backup.log 2>&1

# Use full paths β€” cron has minimal PATH
0 1 * * * /usr/bin/python3 /home/user/job.py

Essential Commands

find Β· sort Β· cut Β· tr Β· wc Β· head Β· tail
find & file operations
# find files
find . -name "*.log"        # by name
find . -type f -newer ref.txt # newer than
find . -size +10M            # larger than 10MB
find . -mtime -7             # modified <7 days
find . -name "*.tmp" -delete # find + delete
find . -name "*.sh" -exec chmod +x {} \;

# Useful text commands
wc -l file.txt       # count lines
wc -w file.txt       # count words
head -n 20 file.txt  # first 20 lines
tail -n 20 file.txt  # last 20 lines
tail -f app.log      # follow live
sort file.txt        # sort lines
sort -r file.txt     # reverse sort
sort -n file.txt     # numeric sort
uniq file.txt        # remove duplicates
uniq -c file.txt     # count occurrences
cut Β· tr Β· paste Β· join
# cut β€” extract columns
cut -d: -f1 /etc/passwd     # field 1 (: delim)
cut -d, -f1,3 data.csv      # fields 1 and 3
cut -c1-10 file.txt         # characters 1-10

# tr β€” translate characters
echo "hello" | tr a-z A-Z    # HELLO
echo "a:b:c" | tr ':' ','    # a,b,c
echo "hello" | tr -d l       # heo (delete l)
echo "  a  b  " | tr -s ' '  # squeeze spaces

# Practical pipeline
cat access.log |
  awk '{print $1}' |   # extract IPs
  sort |               # sort IPs
  uniq -c |            # count unique
  sort -rn |           # top first
  head -10             # top 10 IPs

Error Handling & Best Practices

set -e Β· set -u Β· trap Β· exit codes
Strict mode β€” safer scripts
#!/bin/bash
# Put at top of every script

set -e       # exit on any error
set -u       # error on undefined vars
set -o pipefail  # pipe fails if any cmd fails

# Shorthand for all three
set -euo pipefail

# Check exit code manually
cp file.txt /backup/
if [[ $? -ne 0 ]]; then
  echo "Backup failed" >&2
  exit 1
fi

# Or use || for inline check
cp file.txt /backup/ || {
  echo "Backup failed" >&2
  exit 1
}
trap β€” cleanup on exit
#!/bin/bash
set -euo pipefail

# Create temp file
TMP=$(mktemp)

# Cleanup function
cleanup() {
  echo "Cleaning up..."
  rm -f "$TMP"
}

# Register trap: run cleanup on...
trap cleanup EXIT    # always on exit
trap cleanup ERR     # on error
trap cleanup INT     # on Ctrl+C
trap cleanup TERM    # on kill signal

# Trap multiple signals at once
trap cleanup EXIT ERR INT TERM

# Script body
echo "Working..." > "$TMP"
# cleanup() always runs at end
Script template & logging
#!/bin/bash
set -euo pipefail

# Logging helpers
log()   { echo "[INFO]  $*";        }
warn()  { echo "[WARN]  $*" >&2;   }
error() { echo "[ERROR] $*" >&2;   }
die()   { error "$@"; exit 1; }

# Usage / help
usage() {
  echo "Usage: $0 <input> <output>"
  exit 1
}

[[ $# -lt 2 ]] && usage

log "Starting script"
# ... script body ...
log "Done"
Always use set -euo pipefail at the top of every script. Without it, bash silently ignores errors and continues β€” which can cause data loss or corrupted state. Also always write to stderr with >&2 for error messages.

Shell Scripting Mastery Checklist

sheet 3 complete
Basics & VariablesKey point
Write a valid shebang line #!/bin/bash
Assign and read variables VAR=val / "$VAR"
Use special variables $1 $@ $# $? $$
Capture command output VAR=$(command)
Write conditionals correctly [[ ]] with -eq -gt -z
Write for / while loops for i in ... / while [[ ]]
Pipes & Text ToolsKey point
Redirect stdout to file > (overwrite) / >> (append)
Redirect stderr 2> errors.log
Pipe commands together cmd1 | cmd2 | cmd3
Search with grep grep -inrv "pattern" file
Replace text with sed sed 's/old/new/g' file
Extract columns with awk awk '{print $2}' file
Functions & SafetyKey point
Define and call a function fn() { ... } / fn args
Use local variables local VAR=value
Enable strict mode set -euo pipefail
Register cleanup with trap trap cleanup EXIT ERR
Schedule a cron job crontab -e / min hr * * *
Use cron shortcuts @daily @weekly @reboot
Other Languages series complete!  Β·  You've covered Scala Β· Dart Β· Shell Scripting. Explore more series on Dataplexa β€” Python, Java, Rust, Data Science, AWS Cloud, and more.