C.W.K.
Stream
Lesson 06 of 12 · published

Functions in Scripts

~10 min · function, local, return

Level 0Window Tourist
0 XP0/95 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete

The shape

greet() {
  local name="${1:?name required}"
  echo "hi, $name"
}
greet Pippa

Functions take positional args ($1, $2, $@, $#) just like the script itself. Always local your function variables — without it they leak to the caller's scope.

Return values

return N sets $? for the caller. The N must be 0–255. To return a string, echo it and capture with $( ):

upper() { echo "${1^^}"; }   # bash 4+
name="$(upper hello)"

Variable scope traps

# Bug: leaks 'tmp' to caller
f() { tmp=42; echo $tmp; }
tmp=hello
f         # 42
echo $tmp  # 42, not hello!

# Fix
f() { local tmp=42; echo $tmp; }

Exporting functions

By default, functions defined in a shell are NOT visible to child processes. export -f myfunc makes it visible to bash subshells (zsh works differently). Most scripts don't need this.

Library scripts

Put helpers in lib.sh and load with source ./lib.sh (or . ./lib.sh). Functions become available in the calling shell. Common pattern: a top-level entry script + several library files of helpers, all sourced once at start.

Code

lib.sh + entry pattern·bash
# lib.sh
log()  { printf '%(%H:%M:%S)T %s\n' -1 "$*" >&2; }
die()  { log "FATAL: $*"; exit 1; }

# entry.sh
#!/usr/bin/env bash
set -euo pipefail
source "$(dirname "$0")/lib.sh"
log 'starting'
[[ $# -eq 1 ]] || die 'usage: entry <name>'

External links

Exercise

Write lib.sh with log and die helpers. Source it from a small script. Add a local variable inside one function and verify it doesn't leak by re-reading the same name after the function returns.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.