📜 Part of Pranav Kulkarni's technical portfolio Visit pranavkulkarni.org →
Lesson 2 · Shell Scripting

Advanced Shell Programming

Master advanced techniques: arrays, parameter expansion, traps, and subshells.

Arrays

Arrays help you manage lists without fighting word-splitting. Use "${arr[@]}" to preserve elements safely.

files=(*.txt)
echo "${files[0]}" # First element
echo "${files[@]}" # All elements
echo "${#files[@]}" # Array length

Associative arrays (key → value)

Great for lookups (like a tiny dictionary):

declare -A ports
ports[ssh]=22
ports[https]=443
echo "SSH: ${ports[ssh]}"

Reading files safely (mapfile)

Avoid for x in $(cat file) (it breaks on spaces). Use mapfile or while read.

mapfile -t lines < hosts.txt
for host in "${lines[@]}"; do
echo "Pinging $host"
done

Parameter Expansion

Parameter expansion is Bash’s “string toolbox”: defaults, trimming, substring, replacements.

file="document.tar.gz"
echo "${file%.gz}" # document.tar
echo "${file##*.}" # gz
echo "${file/tar/zip}" # document.zip.gz
# Defaults + required vars
: "${ENVIRONMENT:?Missing ENVIRONMENT}"
timeout="${TIMEOUT:-30}"

# Substring
echo "${file:0:8}" # document

Subshells & Process Substitution

Parentheses run a command list in a subshell. Process substitution (<(cmd)) lets you treat command output like a file.

# Subshell: changes don't affect parent shell
( cd /tmp && touch testfile )
pwd # still your original directory

# Compare two command outputs
diff <(sort a.txt) <(sort b.txt)

Traps

Traps run cleanup logic on exit or signals. This is essential for scripts that create temp files or lock files.

cleanup() { rm -f /tmp/myfile; }
trap cleanup EXIT

Better cleanup with mktemp

tmp="$(mktemp)"
cleanup() { rm -f "$tmp"; }
trap cleanup EXIT
echo "work" > "$tmp"

File Descriptors and Redirection

Power scripts often separate stdout (data) from stderr (logs/errors). This makes pipelines predictable.

# Send logs to stderr
log() { echo "[INFO] $*" >&2; }
log "Starting"

# Redirect stderr to a file
command 2> errors.log

✅ Practice (20 minutes)

  • Use an associative array to map service names to ports and print them.
  • Create a script that uses mktemp + trap to safely handle temp files.
  • Use process substitution to diff sorted outputs of two files.