8.1. Defining Functions#
8.1.1. Common Pitfalls#
1. Forgetting parentheses for POSIX compatibility
# Bash-specific (may not work in sh/dash)
function my_func {
echo "hello"
}
# POSIX-compatible (preferred)
my_func() {
echo "hello"
}
2. Using global variables when local is better
# Bad: Pollutes global scope
process_data() {
temp_value=$1 # Affects global temp_value
echo $temp_value
}
# Good: Use local
process_data() {
local temp_value=$1
echo $temp_value
}
3. Forgetting to quote function parameters
# Problematic with spaces/special characters
echo_name() {
echo "Hello $1" # Unquoted: word splitting occurs
}
# Better
echo_name() {
echo "Hello $1" # Actually the issue is when $1 contains spaces
}
echo_name "Alice Smith" # "Hello Alice Smith" vs "Hello Alice Smith"
8.1.2. Real-World Example: Utility Functions#
#!/bin/bash
# Function to validate that a file exists and is readable
check_file() {
local file=$1
if [[ ! -f "$file" ]]; then
echo "Error: File '$file' does not exist"
return 1
fi
if [[ ! -r "$file" ]]; then
echo "Error: File '$file' is not readable"
return 1
fi
return 0
}
# Function to read and count lines
count_lines() {
local file=$1
wc -l < "$file"
}
# Usage
if check_file "$1"; then
lines=$(count_lines "$1")
echo "File '$1' has $lines lines"
else
echo "Cannot process file"
fi
This example shows:
Functions checking file existence/permissions
Functions returning values via output
Error handling with exit codes
Functions used in conditional logic
8.1.3. Function Scope and Variables#
Variables defined in functions are global by default (visible to the rest of the script). Use the local keyword to create function-scoped variables.
8.1.3.1. Local Variables#
#!/bin/bash
# Global variable
count=0
increment() {
local count=1 # This shadows the global count in function scope
count=$((count + 1))
echo "In function: count=$count"
}
echo "Before: count=$count"
increment
echo "After: count=$count"
# Output:
# Before: count=0
# In function: count=2
# After: count=0
The local keyword ensures changes don’t affect the outer scope.
8.1.4. Function Invocation Patterns#
8.1.4.1. Simple Function Call#
function_name # Call with no arguments
function_name arg1 # Call with one argument
function_name arg1 arg2 # Call with multiple arguments
8.1.4.2. Capturing Function Output#
#!/bin/bash
get_timestamp() {
date "+%Y-%m-%d %H:%M:%S"
}
# Capture output with command substitution
current_time=$(get_timestamp)
echo "Current time: $current_time"
# Or use in a pipeline
if get_timestamp | grep -q "2024"; then
echo "We're in 2024"
fi
8.1.4.3. Using Functions in Command Substitution#
#!/bin/bash
calculate() {
echo $((2 + 2))
}
# Output becomes the result
result=$(calculate)
echo "2 + 2 = $result" # Output: 2 + 2 = 4
8.1.5. Functions with Parameters#
Functions receive arguments just like scripts do, using $1, $2, $#, and $@.
8.1.5.1. Accessing Function Parameters#
#!/bin/bash
# Function that uses parameters
greet_person() {
local name=$1
local greeting=$2
echo "$greeting, $name!"
}
# Call with arguments
greet_person "Alice" "Hello"
greet_person "Bob" "Good morning"
# Output:
# Hello, Alice!
# Good morning, Bob!
Each function invocation has its own parameter scope. $1 in the function refers to the first argument passed to that function call, not to the script’s arguments.
8.1.5.2. Variable Number of Arguments#
#!/bin/bash
# Function that handles variable arguments
print_all() {
echo "You passed $# arguments:"
for arg in "$@"; do
echo " - $arg"
done
}
print_all "apple" "banana" "cherry"
# Output:
# You passed 3 arguments:
# - apple
# - banana
# - cherry
8.1.6. Function Basics: Syntax and Structure#
A bash function is a named block of code that can be called multiple times. Functions accept parameters (positional arguments) and return status codes.
8.1.6.1. Function Definition Syntax#
There are two ways to define a function in bash:
Method 1: function keyword
function function_name {
# function body
commands
}
Method 2: parentheses
function_name() {
# function body
commands
}
Both forms are equivalent. The parentheses form is more portable (POSIX-compatible), while the function keyword is bash-specific but more readable.
8.1.6.2. Simple Function Example#
#!/bin/bash
# Define a simple greeting function
greet() {
echo "Hello, World!"
}
# Call the function
greet
# Output: Hello, World!