0
0
Bash Scriptingscripting~15 mins

Function libraries (sourcing scripts) in Bash Scripting - Deep Dive

Choose your learning style9 modes available
Overview - Function libraries (sourcing scripts)
What is it?
Function libraries in bash scripting are files that contain reusable functions. Instead of writing the same code repeatedly, you keep these functions in a separate script file. You then 'source' this file in your main script to use those functions. This helps keep your scripts clean and organized.
Why it matters
Without function libraries, scripts become long and repetitive, making them hard to read and maintain. If you want to fix a bug or add a feature, you’d have to change many scripts separately. Function libraries let you write code once and reuse it everywhere, saving time and reducing errors.
Where it fits
Before learning function libraries, you should know basic bash scripting and how to write functions. After this, you can learn about script modularization, advanced script debugging, and automation workflows that use multiple scripts working together.
Mental Model
Core Idea
Sourcing a script is like borrowing a toolbox full of ready-made tools (functions) to use in your current project without copying them.
Think of it like...
Imagine you have a toolbox at home with all your tools. Instead of buying new tools every time you fix something, you just bring your toolbox to the job. Sourcing a script is like bringing that toolbox into your workspace.
Main Script
  │
  ├─ sources ──> Function Library Script
  │               ├─ function1()
  │               ├─ function2()
  │               └─ function3()
  │
  └─ uses functions from library
Build-Up - 7 Steps
1
FoundationWriting simple bash functions
🤔
Concept: Learn how to write basic functions in bash scripts.
A bash function is a block of code you can call by name. For example: my_function() { echo "Hello from my function" } You call it by writing: my_function This helps avoid repeating code.
Result
When you run the script and call my_function, it prints: Hello from my function
Understanding how to write and call functions is the first step to reusing code and organizing scripts.
2
FoundationRunning scripts vs sourcing scripts
🤔
Concept: Understand the difference between executing a script and sourcing it.
Running a script (./script.sh) starts a new shell process. Variables and functions inside it don't affect your current shell. Sourcing a script (source script.sh or . script.sh) runs the script in your current shell. Functions and variables become available immediately. Try: $ cat lib.sh my_func() { echo "Hi"; } $ ./lib.sh $ my_func # Error: command not found $ source lib.sh $ my_func Hi
Result
After sourcing, you can use functions defined in the sourced script directly in your shell.
Knowing sourcing lets you share functions and variables between scripts or your shell session without running separate processes.
3
IntermediateCreating and using function libraries
🤔Before reading on: do you think sourcing a library script multiple times redefines functions or causes errors? Commit to your answer.
Concept: Learn how to organize functions in a separate file and use them in multiple scripts by sourcing.
Put your reusable functions in a file, e.g., lib.sh: say_hello() { echo "Hello, $1" } In your main script: #!/bin/bash source ./lib.sh say_hello "Alice" Run main script, it prints: Hello, Alice If you source lib.sh multiple times, functions get redefined but bash allows it without error.
Result
Main script can call say_hello from the library, printing the greeting.
Separating functions into libraries makes scripts cleaner and easier to maintain, and sourcing shares code without duplication.
4
IntermediateHandling variables and scope in sourced scripts
🤔Before reading on: do you think variables set in a sourced script remain after sourcing? Commit to your answer.
Concept: Understand how variables behave when scripts are sourced and how to avoid conflicts.
When you source a script, variables it sets become part of your current shell environment. Example: lib.sh: MY_VAR="Hello" main.sh: source ./lib.sh echo $MY_VAR Output: Hello To avoid overwriting variables, use local variables inside functions or unique variable names. Example: my_func() { local temp="temp value" echo $temp } Local variables exist only inside the function.
Result
Variables set in sourced scripts persist unless declared local inside functions.
Knowing variable scope prevents bugs from unexpected variable overwrites when sourcing multiple scripts.
5
IntermediateUsing conditional sourcing to avoid reloading
🤔Before reading on: do you think sourcing the same library twice can cause problems? Commit to your answer.
Concept: Learn how to prevent sourcing a library multiple times using guards.
To avoid redefining functions or variables, use a guard variable: In lib.sh: if [ -z "$LIB_SH_INCLUDED" ]; then LIB_SH_INCLUDED=1 say_hello() { echo "Hello, $1" } fi This way, if lib.sh is sourced again, the code inside the if-block won't run again. Try sourcing lib.sh twice and call say_hello to see it works without errors.
Result
Functions and variables are defined only once, even if sourced multiple times.
Using guards protects your scripts from accidental multiple sourcing, which can cause subtle bugs.
6
AdvancedPassing arguments and returning values in functions
🤔Before reading on: do you think bash functions can return strings directly? Commit to your answer.
Concept: Understand how to pass inputs to functions and get outputs in bash.
Functions receive arguments as $1, $2, etc. Example: add() { echo $(($1 + $2)) } result=$(add 3 4) echo $result Output: 7 Bash functions can't return strings directly with return; return only returns an exit code (number 0-255). Use echo and command substitution to get string outputs.
Result
You can pass inputs and capture outputs from functions using arguments and echo.
Knowing how to handle inputs and outputs in bash functions is key to building flexible reusable code.
7
ExpertAdvanced sourcing: dynamic libraries and environment isolation
🤔Before reading on: do you think sourcing a script can affect your current shell environment permanently? Commit to your answer.
Concept: Explore advanced patterns like dynamically sourcing libraries and isolating environment changes.
Sourcing runs code in your current shell, so any variable or function changes persist. To avoid polluting your environment, you can: - Use subshells: (source lib.sh; commands) runs in a subshell, changes discarded after. - Use dynamic sourcing: choose which library to source based on conditions. Example: if [ "$USE_LIB" = "v2" ]; then source lib_v2.sh else source lib_v1.sh fi This allows flexible script behavior. Beware: sourcing untrusted scripts can change your environment unexpectedly.
Result
You can control which functions are loaded and keep your environment clean using subshells or conditional sourcing.
Understanding sourcing's environment impact helps prevent hard-to-debug side effects and enables flexible script design.
Under the Hood
When you source a script, the shell reads and executes each line as if you typed it directly in your current shell session. Functions and variables defined become part of the current shell's environment. Unlike running a script, which creates a new shell process, sourcing shares the same process and environment. This means changes persist and can affect later commands.
Why designed this way?
Sourcing was designed to allow scripts to share code and environment easily without spawning new processes. This saves system resources and enables modular scripting. Alternatives like running scripts separately isolate environments but prevent sharing. The tradeoff is that sourcing can cause side effects if not managed carefully.
Current Shell Environment
  ├─ source lib.sh
  │    ├─ read line 1: define function
  │    ├─ read line 2: set variable
  │    └─ execute commands
  └─ functions and variables now available in current shell
Myth Busters - 4 Common Misconceptions
Quick: Does sourcing a script run it in a new shell process? Commit to yes or no.
Common Belief:Sourcing a script runs it in a new shell process, so it doesn't affect the current shell.
Tap to reveal reality
Reality:Sourcing runs the script in the current shell process, so all functions and variables become part of the current environment.
Why it matters:Believing sourcing runs in a new process leads to confusion when variables or functions defined in sourced scripts are unexpectedly available or when changes persist.
Quick: Can bash functions return strings using the return statement? Commit to yes or no.
Common Belief:Bash functions can return strings directly using the return statement.
Tap to reveal reality
Reality:The return statement in bash functions only returns an integer exit code (0-255). To return strings, functions must output them with echo and use command substitution.
Why it matters:Misunderstanding this causes bugs when scripts expect string outputs from return, leading to unexpected empty or wrong values.
Quick: Does sourcing the same library multiple times cause errors? Commit to yes or no.
Common Belief:Sourcing the same script multiple times causes errors or function redefinition conflicts.
Tap to reveal reality
Reality:Bash allows functions and variables to be redefined without error, so multiple sourcing usually doesn't cause immediate errors but can cause unexpected behavior.
Why it matters:Ignoring this can lead to subtle bugs or performance issues if libraries are sourced repeatedly without guards.
Quick: Do variables declared in sourced scripts always stay local? Commit to yes or no.
Common Belief:Variables in sourced scripts are local by default and don't affect the current shell environment.
Tap to reveal reality
Reality:Variables set in sourced scripts are global in the current shell unless declared local inside functions.
Why it matters:Assuming variables are local can cause accidental overwriting of important variables, leading to hard-to-find bugs.
Expert Zone
1
Sourcing a script affects the current shell environment permanently, so careful naming and scoping are essential to avoid conflicts.
2
Using guard variables to prevent multiple sourcing is a best practice but often overlooked, leading to subtle bugs in large projects.
3
Dynamic sourcing based on environment variables or conditions enables flexible script behavior but requires careful management to avoid unpredictable states.
When NOT to use
Avoid sourcing when you want to isolate script execution to prevent environment pollution. Instead, run scripts as separate processes. For complex projects, consider using configuration management tools or languages with better modularization support like Python.
Production Patterns
In production, function libraries are organized into well-named files with guard variables. Scripts source only needed libraries conditionally. Environment variables are carefully managed to avoid conflicts. Logging and error handling functions are centralized in libraries for reuse.
Connections
Modular programming
Function libraries in bash are a form of modular programming, breaking code into reusable parts.
Understanding modular programming principles helps design better function libraries that are easy to maintain and extend.
Shared libraries in compiled languages
Sourcing bash scripts is similar to linking shared libraries in compiled languages like C, where code is reused without duplication.
Knowing this connection clarifies why sourcing is efficient and how it fits into software reuse concepts.
Human teamwork and tool sharing
Just like people share tools to work efficiently, scripts share functions by sourcing libraries.
This cross-domain view highlights the universal value of sharing resources to avoid duplication and improve productivity.
Common Pitfalls
#1Accidentally overwriting variables from sourced scripts.
Wrong approach:source lib.sh MY_VAR="new value" # Later expecting original MY_VAR from lib.sh
Correct approach:source lib.sh # Use unique variable names or local variables inside functions to avoid overwriting
Root cause:Not understanding that sourcing shares the same environment and variables can be overwritten.
#2Sourcing the same library multiple times without guards.
Wrong approach:source lib.sh source lib.sh # Functions redefined multiple times
Correct approach:In lib.sh: if [ -z "$LIB_SH_INCLUDED" ]; then LIB_SH_INCLUDED=1 # function definitions fi source lib.sh source lib.sh # Safe multiple sourcing
Root cause:Not using guard variables to prevent repeated sourcing.
#3Expecting bash functions to return strings with return statement.
Wrong approach:my_func() { return "hello" } result=$(my_func) echo $result # Prints empty
Correct approach:my_func() { echo "hello" } result=$(my_func) echo $result # Prints hello
Root cause:Misunderstanding bash function return semantics.
Key Takeaways
Sourcing scripts lets you reuse functions and variables by running code in the current shell environment.
Always use guard variables in libraries to prevent problems from sourcing them multiple times.
Bash functions use echo and command substitution to return strings, not the return statement.
Variables set in sourced scripts affect the current shell unless declared local inside functions.
Understanding sourcing deeply helps you write modular, maintainable, and efficient bash scripts.