Shell Scripting Roadmap
Four stages, each gated by a capability rather than a lesson count. Every stage ends with a concrete check — something you can either do or cannot — so progress is measurable rather than a feeling.
The two edges that actually matter
Most lessons can be taken in any order within a stage. Two dependencies are not optional: quoting before everything — loops, arrays and file reading are all unsafe without it; and error handling before scheduling — an unattended job that cannot fail loudly is worse than no job at all.
Stage 1 — Beginner
~1.5hWrite a script that does not break on a filename with a space
Comfortable in a terminal: cd, ls, editing a file.
- ▸ Write and run an executable script with a correct shebang
- ▸ Quote every expansion correctly and explain what breaks without it
- ▸ Take arguments and return meaningful exit codes
- ▸ Branch with [[ ]] and loop over files safely
- ▸ Use arrays instead of space-delimited strings
You can write a script that correctly processes a directory containing a file named "my report (final).txt" — and explain why `for f in $(ls)` cannot.
Stage 2 — Intermediate
~3hWrite a script other people can run in production
Beginner stage. Especially quoting — everything here assumes it.
- ▸ Structure code into functions with correct scope and return values
- ▸ Wire file descriptors deliberately; use here-docs and process substitution
- ▸ Replace multi-stage pipelines with a single awk program
- ▸ Read any file safely, including filenames containing newlines
- ▸ Apply strict mode and know the five places it stops protecting you
- ▸ Debug with an annotated PS4 trace and an ERR trap
- ▸ Split a growing script into sourceable libraries
- Functions, Scope & Return Values 17m
- Pipes, Redirection, Here-Docs & Process Substitution 18m
- The Text Processing Toolkit 16m
- awk & sed in Depth 19m
- Reading Files & Streams Safely 16m
- Error Handling & the Limits of Strict Mode 19m
- Debugging, Tracing & Making Scripts Observable 16m
- Modular Scripts, Libraries & Project Layout 16m
- Project Backup & Restore System 45m
Your script survives `set -Eeuo pipefail`, cleans up after itself on Ctrl+C, and a colleague can run it from any working directory without reading the source.
Stage 3 — Advanced
~4hWrite a script the on-call rotation depends on
Intermediate stage. Error handling is load-bearing from here.
- ▸ Build a proper CLI with getopts, subcommands and conventional exit codes
- ▸ Manage background jobs, collect per-job status, clean up children
- ▸ Schedule work that survives cron's environment, with locking and timeouts
- ▸ Drive fleets over SSH and consume APIs with curl + jq reliably
- ▸ Alert with damping, deduplication and recovery notices
- ▸ Pass ShellCheck cleanly and know what breaks under /bin/sh
- ▸ Test shell with bats and keep secrets out of ps, logs and traces
- Building Real CLI Tools with getopts 17m
- Background Jobs, Signals & Parallel Execution 18m
- Cron, systemd Timers & Safe Scheduling 16m
- Remote Operations & Working with APIs 18m
- Log Analysis, Monitoring & Alerting 17m
- ShellCheck, Style & POSIX Portability 17m
- Testing, Secrets & Knowing When to Leave Bash 18m
You ship a tool with --help, --dry-run, distinct exit codes and a bats suite, and it runs unattended for a month without anyone touching it.
Stage 4 — Expert
~3.5hKnow when not to write the script at all
Advanced stage plus the first three projects.
- ▸ Design for reversibility — rollback as the primary path, not the error path
- ▸ Normalise heterogeneous inputs so correlation becomes trivial
- ▸ Judge the ~100-line boundary and hand off to Python deliberately
- ▸ Build alerting humans do not mute
- ▸ Review someone else's shell and name the failure before it happens
You can look at a 400-line bash script and say precisely which 80 lines should stay shell and which 320 should be a Python module — and justify the split.
When to stop writing shell
Expert judgement is mostly knowing the boundary. Google's style guide puts it at roughly 100 lines, or any script doing non-trivial data manipulation. Past that, the things bash lacks start costing more than the glue it saves.
Shell remains the right tool when the script is mostly calling other programs and the data flow is linear. Reaching for a real language when the logic outgrows the glue is the senior call, not a defeat.
Interview readiness
The questions that come up most, and where each is answered.
- 1 What is shell scripting, and when would you not use it? modular-scripts-and-libraries →
- 2 Explain the shebang. What does the kernel do with it? shell-basics-and-execution →
- 3 Difference between $@ and $* quoting-and-expansion →
- 4 What is $? and how do you use it? arguments-and-exit-codes →
- 5 for vs while — when does each fit? loops-and-control-flow →
- 6 How do you handle errors in a shell script? error-handling-and-strict-mode →
- 7 What are file test operators? conditionals-and-tests →
- 8 Explain pipes and redirection pipes-redirection-heredocs →
- 9 Why does `cmd 2>&1 > file` not do what it looks like? pipes-redirection-heredocs →