Przejdลบ do treล›ci

๐Ÿงฑ Extended Functions and Libraries

Functions encapsulate reusable logic. Libraries organize shared code across multiple scripts. This section covers both in depth.

๐Ÿงญ Defining Functions

Two syntaxes (both equivalent):

1
2
3
4
5
6
7
8
9
# Style 1: function keyword
function greet {
    echo "Hello, $1!"
}

# Style 2: Parentheses (preferred in Bash)
greet() {
    echo "Hello, $1!"
}

Call the function:

1
greet "Alice"   # Outputs: Hello, Alice!


๐Ÿงช Passing Arguments

Inside functions, positional parameters are local:

1
2
3
4
5
6
7
8
9
show_args() {
    echo "Script name: $0"
    echo "Function name: $FUNCNAME"   # Bash/Zsh
    echo "First arg: $1"
    echo "All args: $@"
    echo "Arg count: $#"
}

show_args hello world "foo bar"

Output:

1
2
3
4
5
Script name: ./script.sh
Function name: show_args
First arg: hello
All args: hello world foo bar
Arg count: 3


๐Ÿง  Returning Values

Shell functions don't return values like other languages. Instead:

Method 1: Echo Output (Most Common)

1
2
3
4
5
6
get_current_date() {
    date +%Y-%m-%d
}

today=$(get_current_date)
echo "Today is $today"

Method 2: Global Variable

1
2
3
4
5
6
calculate_total() {
    total=$(( $1 + $2 ))
}

calculate_total 10 20
echo "Total: $total"   # 30

โš ๏ธ Modifies global scope โ€” use carefully.

Method 3: Exit Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
validate_input() {
    [ -z "$1" ] && return 1
    return 0
}

if validate_input "$user_input"; then
    echo "Valid"
else
    echo "Invalid"
fi

๐Ÿงช Local Variables

Prevent pollution of global scope:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
process_file() {
    local filename="$1"
    local temp_dir
    temp_dir=$(mktemp -d)

    # Do work with $temp_dir
    cp "$filename" "$temp_dir/"

    # Cleanup
    rm -rf "$temp_dir"
}

local ensures variables don't leak outside the function.


๐Ÿง  Organizing Libraries

Simple Library File

lib/utils.sh

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#!/bin/sh

log_msg() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >&2
}

die() {
    log_msg "ERROR: $*"
    exit 1
}

require_file() {
    [ -f "$1" ] || die "Required file not found: $1"
}

Including Libraries

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#!/bin/sh

# Determine script directory
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"

# Source library
. "$SCRIPT_DIR/lib/utils.sh"

# Use functions
log_msg "Starting process..."
require_file config.yml
log_msg "Config found"

The . command (or source) loads functions into current shell context.


๐Ÿงช Advanced Library Patterns

Namespaced Functions

Avoid name collisions:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
db_connect() {
    echo "Connecting to database..."
}

db_disconnect() {
    echo "Disconnecting from database..."
}

http_connect() {
    echo "Connecting to HTTP..."
}

Prefix with module name for clarity.

Conditional Loading

Load only if not already defined:

1
2
3
if ! command -v log_msg >/dev/null 2>&1; then
    . ./lib/logging.sh
fi

Or check function existence:

1
2
3
if ! declare -f log_msg >/dev/null; then
    . ./lib/logging.sh
fi

๐Ÿง  Recursive Functions

Bash supports recursion (enable with shopt -s extdebug in some cases):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
factorial() {
    local n=$1
    if [ $n -le 1 ]; then
        echo 1
    else
        local prev=$(factorial $((n - 1)))
        echo $((n * prev))
    fi
}

echo "5! = $(factorial 5)"   # 120

โš ๏ธ Deep recursion may hit stack limits โ€” use iteration for large inputs.


๐Ÿงช Anonymous Functions (Bash 4.4+)

Define inline functions:

1
2
3
4
5
6
7
8
9
map() {
    local fn=$1
    shift
    for item; do
        "$fn" "$item"
    done
}

map 'echo "Processing: $1"' apple banana cherry

๐Ÿงพ Portability Notes

Feature POSIX Bash Zsh
Function definition โœ… โœ… โœ…
local variables โœ… โœ… โœ…
$FUNCNAME โŒ โœ… โœ…
Recursion โš ๏ธ โœ… โœ…
Anonymous functions โŒ โœ… โŒ
Arrays as args โŒ โœ… โœ…

๐Ÿงพ Summary

  • Use functions to avoid code duplication.
  • Always use local for variables inside functions.
  • Return values via stdout or exit codes.
  • Organize shared code in library files.
  • Source libraries with . or source.
  • Prefix function names to avoid collisions.

๐Ÿ‘‰ Continue to: Error Handling