Functions & arguments
Group commands into reusable units, accept positional parameters, and return exit codes. Not quite like functions in 'real' languages.
Scoping: Bash uses dynamic scoping, not lexical. A local var in function A is visible to function B if B is called from A. This is different from most languages and occasionally surprises people. Always declare local for anything you don't intend to leak to callers.
Argument handling: $# (count), $@ (all args, use quoted "$@"), $1..$9, ${10}..${99}. shift Ndrops the first N args. Functions see the CALLER's$0but their OWN$1..$@. Idiom: set --clears positional params;set -- a b c` sets them.
Returning data — three patterns: (1) echo the result, capture with command substitution: x=$(fn). (2) Assign to a global: fn() { result=42; }. (3) Bash 4.3+ declare -n ref=$1; ref=42 (name references — the closest to by-reference output). Choose based on clarity; pattern 1 is most common but fork-heavy for tight loops.
Error handling inside functions: under set -e, a failing command in a function exits the shell. But if fn; then disables set -e inside fn — a well-known Bash wart. For reliable function error-handling, check exit codes explicitly or structure as fn || die 'fn failed'.
Namespacing & libraries: Bash has no modules. Convention: source lib.sh (same as . lib.sh) loads a file into the current shell — functions become available. Prefix function names to avoid collisions: myapp::init works (Bash allows : in names, but only if the first char is letter/underscore). Large projects use this for pseudo-namespaces.
Anti-patterns: (i) functions that echo debug info — pollutes command substitution callers; route diagnostics to stderr (>&2). (ii) forgetting local → 'mysterious' variable mutations. (iii) return "$str" when $str is non-numeric → runtime error. (iv) functions longer than ~40 lines — split them or move to a separate script.
Grounded on https://www.gnu.org/software/bash/manual/bash.html#Functions
Next up
Globbing & expansions
Wildcards for filenames, brace expansion for lists, parameter expansion for string ops. The shell rewrites your command line before running it.