Script Valley
Bash Scripting for Developers
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

Bash script structure layout

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 equivalent

Guard 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.

Up next

How to write a Bash logging library

Sign in to track progress

Bash script structure and sourcing files โ€” Functions and Script Architecture โ€” Bash Scripting for Developers โ€” Script Valley โ€” Script Valley