Shell by Example: Functions POSIX + Bash

Functions let you group commands together and reuse them throughout your script. They’re essential for organizing larger scripts.

Define a function using the name() { } syntax. The function keyword is optional and not POSIX.

Edit
#!/bin/sh
greet() {
    echo "Hello, World!"
}

Bash

Bash supports an alternative syntax using the function keyword:

Edit
#!/bin/bash
function greet {
    echo "Hello, World!"
}

Bash

You can also combine both syntaxes:

Edit
#!/bin/bash
function greet() {
    echo "Hello, World!"
}
another_greet_fn() {
    echo "Hello, World!"
}

Bash

Call a function by using its name.

Edit
#!/bin/bash
function greet() {
    echo "Hello, World!"
}
greet
Output:
Hello, World!

Functions can accept arguments via $1, $2, etc.

Edit
#!/bin/sh
greet_user() {
    echo "Hello, $1!"
}

greet_user "Alice"
greet_user "Bob"
Output:
Hello, Alice!
Hello, Bob!

$@ contains all arguments, $# is the count.

Edit
#!/bin/sh
show_args() {
    echo "Number of arguments: $#"
    for arg in "$@"; do
        echo "  - $arg"
    done
}

show_args one two three
Output:
Number of arguments: 3
  - one
  - two
  - three

Functions return exit status with return. Return 0 for success, non-zero for failure.

Edit
#!/bin/sh
is_even() {
    if [ $(($1 % 2)) -eq 0 ]; then
        return 0 # success/true
    else
        return 1 # failure/false
    fi
}

if is_even 4; then
    echo "4 is even"
fi

if ! is_even 7; then
    echo "7 is odd"
fi
Output:
4 is even
7 is odd

To return string values, use command substitution.

Edit
#!/bin/sh
get_greeting() {
    echo "Hello, $1!"
}

message=$(get_greeting "World")
echo "Got: $message"
Output:
Got: Hello, World!

Variables in functions are global by default. Be careful with naming to avoid conflicts.

Edit
#!/bin/sh
counter=0

increment() {
    counter=$((counter + 1))
}

increment
increment
echo "Counter: $counter"
Output:
Counter: 2

Bash

Bash provides the local keyword for function-scoped variables that don’t affect the global namespace:

Edit
#!/bin/bash
calculate() {
    local result=0
    local i
    for i in "$@"; do
        result=$((result + i))
    done
    echo "$result"
}

result="global"
sum=$(calculate 1 2 3 4 5)
echo "Sum: $sum"       # Sum: 15
echo "Result: $result" # Result: global (unchanged)
Output:
Sum: 15
Result: global

Functions must be defined before they’re called. Unlike some languages, shell scripts are interpreted top-to-bottom, so calling an undefined function fails.

Edit
#!/bin/sh
# Calling an undefined function produces an error:
undefined_func 2>&1 || true

# This works: define first, then call
greet() {
    echo "Hello, $1!"
}
greet "World"
Output:
/script: line 7: undefined_func: not found
Hello, World!

« While Loops | Arrays »