🎓 A1Learner
🔍
0 of 45 lessons completed

Bash Script Libraries

A Bash script library is a file of reusable functions that other scripts load with source. Libraries keep shared logic in one place, so one fix reaches every script that loads them.

A double-source guard loads a library once

The library prints a loaded line, then defines greet. It is sourced twice, but the loaded line appears once, which proves the guard worked.

cat > greet.sh <<'LIBEOF'
if [[ -n "${_GREET_LOADED:-}" ]]; then
  return 0
fi
_GREET_LOADED=1
echo "library loaded"
greet() {
  echo "hello $1"
}
LIBEOF
source greet.sh
source greet.sh
greet Ada

A main guard runs only when executed directly

Running tool.sh prints its main line. Sourcing it in a subshell prints no main line, which proves the guard told the two cases apart.

cat > tool.sh <<'TOOLEOF'
main() {
  echo "tool ran"
}
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
  main "$@"
fi
TOOLEOF
bash tool.sh
( source tool.sh; echo "sourced, main did not run" )

A library path follows the script, not the working directory

The app finds its own directory from BASH_SOURCE and sources the library from there. The sum 5 proves the library loaded from that relative path.

mkdir lib
cat > lib/math.sh <<'MATHEOF'
add() {
  echo $(( $1 + $2 ))
}
MATHEOF
cat > app.sh <<'APPEOF'
DIR="$(dirname "${BASH_SOURCE[0]}")"
source "$DIR/lib/math.sh"
add 2 3
APPEOF
bash app.sh

Example

cat > lib.sh <<'LIBEOF'
if [[ -n "${_APP_LIB_LOADED:-}" ]]; then
  return 0
fi
_APP_LIB_LOADED=1
LIB_VERSION="1.2.0"
log() {
  echo "log: $1"
}
double() {
  echo $(( $1 * 2 ))
}
LIBEOF
source lib.sh
source lib.sh
echo "library version $LIB_VERSION"
log "starting work"
echo "double of 21 is $(double 21)"

Key points

  • Source: source loads a library file into the current shell, so its functions stay available.
  • Double-source guard: a loaded flag plus an early return stops a library from running twice.
  • Main pattern: compare BASH_SOURCE[0] with $0 so a file runs its main part only when executed directly.
  • Location: derive a library path from dirname of BASH_SOURCE[0] instead of assuming the working directory.
  • Namespace: prefix library functions with a short name so they do not clash with other code.
  • Version stamp: keep a version variable in the library so scripts can report which library they loaded.
  • No side effects: a library should define functions only, and never run work on load.

In this example, a library file defines a version variable and two functions, behind a double-source guard. The main script sources the library twice, but the guard stops the second load. It then prints the library version, writes one log line, and doubles 21 to 42.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

A script sources the same library twice. What does a double-source guard prevent?