Function Arguments, Return Codes, and Output Capture
Deep dive into how Bash functions receive arguments, signal success or failure with return codes, and communicate results back to callers.
January 17, 20266 min read
BashFunctionsReturn CodesScripting
Understanding the contract between a function and its caller — how arguments flow in, how results flow out, and how success/failure is signalled — is essential for writing Bash functions that compose reliably.
Positional Parameters Inside Functions
function show_args {
echo "Function name (via FUNCNAME): ${FUNCNAME[0]}"
echo "Number of args: $#"
echo "All args: $@"
echo "First: $1"
echo "Second: $2"
}
show_args "alpha" "beta" "gamma"
# Function name: show_args
# Number of args: 3
# All args: alpha beta gamma
# First: alpha
# Second: beta
# Note: $0 inside a function is the SCRIPT name, not the function name
# Use ${FUNCNAME[0]} for the function nameValidating Arguments
function create_backup {
local src="${1:?create_backup: source directory required}"
local dest="${2:?create_backup: destination directory required}"
if [[ ! -d "$src" ]]; then
echo "ERROR: source '$src' is not a directory" >&2
return 1
fi
mkdir -p "$dest" || return 1
cp -r "$src/." "$dest/" || return 1
echo "Backup complete: $src → $dest"
return 0
}
# Call and check result
if create_backup "/etc" "/tmp/etc-backup"; then
echo "Success"
else
echo "Backup failed" >&2
fiReturn Codes vs Output
Two communication channels
| Channel | How | Use for |
|---|---|---|
| Exit/return code | return N (0=success) | Success/failure signalling |
| Standard output | echo "value" | Return data values |
| Standard error | echo "msg" >&2 | Error messages, logging |
Callers check exit codes with if, $?, &&, || and capture output with $().
function get_file_size {
local file="$1"
if [[ ! -f "$file" ]]; then
echo "File not found: $file" >&2 # error → stderr
return 1 # signal failure
fi
stat -c%s "$file" 2>/dev/null || wc -c < "$file" # size → stdout
return 0 # signal success
}
# Use it
size=$(get_file_size "/etc/hosts")
if [[ $? -eq 0 ]]; then
echo "Size: $size bytes"
else
echo "Could not get size"
fi
# Cleaner idiom:
if size=$(get_file_size "/etc/hosts"); then
echo "Size: $size bytes"
fiPassing Arrays to Functions
Bash can't pass arrays directly — they're word-split at the call site. Use the nameref trick (Bash 4.3+) or pass via a global variable:
# Method 1: declare -n nameref (Bash 4.3+)
function print_array {
local -n arr=$1 # -n makes arr a nameref to the named variable
for item in "${arr[@]}"; do
echo " - $item"
done
}
fruits=("apple" "banana" "cherry")
print_array fruits # pass the NAME, not the content
# Method 2: use "$@" when the arguments ARE the array elements
function sum_args {
local total=0
for n in "$@"; do (( total += n )); done
echo "$total"
}
numbers=(1 2 3 4 5)
total=$(sum_args "${numbers[@]}")
echo "Sum: $total"Quick Check
A function runs `return 42`. What does `$?` hold immediately after the function call?
Exercise
Write a function find_largest that:
- Takes any number of numeric arguments (use
"$@") - Finds and echoes the largest number
- Returns 0 on success, 1 if no arguments given
- Test it:
largest=$(find_largest 3 1 7 2 5)should givelargest=7