The shape
greet() {
local name="${1:?name required}"
echo "hi, $name"
}
greet PippaFunctions 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.