<aside> 🧱
Module 8 — Functions and Script Structure. Real scripts grow. Functions keep a 300-line deploy script readable, testable, and safe to change.
🧠 concept → 🧩 analogy → 🧪 exercise → ✅ expected result (hidden) → 🎯 interview questions (hidden)
</aside>
<aside> 📋
Before you start. You need Modules 1–7 — especially positional parameters (Module 7: functions reuse that exact machinery), exit codes (Module 3: functions have verdicts too), and source vs execute (Module 1 C1: it returns here with a twist). Tools: nothing new. Keep ~/bash-course.
</aside>
<aside> 📖
Official docs: Bash manual — Shell Functions
</aside>
A function gives a block of commands a name; saying the name later runs the block. The standard form:
log() {
echo "[$(date +%H:%M:%S)] $*"
}
log "deploy starting"
The parentheses are empty punctuation marking "this is a function definition" — arguments do not go there (A2 shows where they go). The body sits in { }. An alternative spelling function log { … } exists in bash; the name() form is the portable convention, and mixing both in one file is a style smell.
One rule follows from bash's nature as a top-to-bottom reader (Module 1): a function must be defined earlier in the file than its first call. There is no hoisting, no lookahead — a call above the definition is just an unknown command (exit 127, Module 3's old friend). Hence the universal layout: functions at the top, action at the bottom — C1 makes that a formal template.
<aside> 🧩
Real-world analogy — the named play. A sports team drills a set-piece until it has a name — "run Falcon!" — and one shouted word triggers the whole rehearsed sequence. Functions are named plays: define once, invoke by name, and the game plan (your main script) reads as strategy instead of choreography.
Where the analogy stops working. A team remembers plays from last season. Bash remembers nothing across runs: definitions live only in the shell that read them, die with it (Module 2's jars), and must appear in every script that uses them — which is why shared functions get a file of their own that scripts source (C2), the closest bash has to a playbook binder.
</aside>
🧪 Exercise 8.1 — name a play
cd ~/bash-course
nano fn1.sh # six lines:
#!/bin/bash
log() {
echo "[$(date +%H:%M:%S)] $*"
}
log "deploy starting"
log "deploy finished"
chmod +x fn1.sh
./fn1.sh
$1 again, wearing a different hat<aside> 📖
Official docs: Bash manual — Shell Functions
</aside>
Arguments go after the function's name at the call, exactly like arguments to a script — and inside the function, they arrive as $1, $2, $#, "$@": the same positional machinery, temporarily re-pointed. For the duration of the call, the function's arguments shadow the script's; when it returns, the script's own $1 is back, untouched. Everything Module 7 taught applies wholesale — quoting, $# guards, shift, even getopts (with the OPTIND reset from Module 7's E2).
🧪 Exercise 8.2 — arguments in, arguments restored