Functions and Script ArchitectureLesson 3.3
Bash script structure and sourcing files
script organization pattern, sourcing with dot operator, source vs execute, library scripts, guard against re-sourcing, __dirname equivalent, relative paths in scripts
Structuring Scripts for Real Projects
Professional Bash scripts follow a consistent structure. This layout makes scripts readable, testable, and safe to source.
#!/usr/bin/env bash
set -euo pipefail
# 1. Resolve script directory (portable)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# 2. Source libraries relative to script, not CWD
source "${SCRIPT_DIR}/lib/logging.sh"
source "${SCRIPT_DIR}/lib/utils.sh"
# 3. Constants
readonly APP_NAME="myapp"
readonly LOG_FILE="/var/log/${APP_NAME}.log"
# 4. Functions
run_backup() {
log INFO "Starting backup..."
# ...
}
# 5. Main entrypoint
main() {
parse_args "$@"
run_backup
}
main "$@"Source vs Execute
# Execute: runs in a subshell, no access to caller's scope
bash lib/helpers.sh
# Source: runs in current shell, shares scope
source lib/helpers.sh
. lib/helpers.sh # POSIX equivalentGuard Against Double-Sourcing
# In lib/logging.sh:
[[ -n "${_LOGGING_SH_LOADED:-}" ]] && return 0
_LOGGING_SH_LOADED=1
log() {
echo "[$(date +%T)] $*" >&2
}Use ${BASH_SOURCE[0]} instead of $0 when resolving paths โ $0 returns the calling script's name when the file is sourced, not the library's name.
