# Shell Functions ## Functions Define reusable code blocks with the `function` keyword or parentheses syntax. Functions reduce code duplication and improve readability. ```bash # Both syntaxes are equivalent function greet() { echo "Hello, $1!" } greet_alt() { echo "Hello, $1!" } # Call the function greet "Alice" ``` Return a status code (0-255) with the `return` statement. The exit code is stored in `$?` and used by conditionals. ```bash check_file() { if [[ -f "$1" ]]; then echo "$1 exists" return 0 else echo "$1 not found" return 1 fi } check_file "/etc/passwd" && echo "Success" || echo "Failed" ``` ## Parameters and Arguments Access positional parameters inside a function with `$1`, `$2`, etc. `$0` is the script name, not the first argument. ```bash process_files() { echo "Function name: $0" echo "First file: $1" echo "Second file: $2" echo "Total arguments: $#" } process_files "file1.txt" "file2.txt" ``` Use `$@` to pass all arguments as separate words (expands each one), and `$*` to pass as a single string. `$#` gives the argument count. ```bash # Iterate over all arguments sum_args() { local total=0 for arg in "$@"; do total=$((total + arg)) done echo $total } sum_args 1 2 3 4 5 # Output: 15 # Note: "$@" is preferred over "$*" to preserve word boundaries ``` ## Special Variables Shell provides automatic variables for introspection and control flow. - `$$` — Process ID of the current shell - `$!` — Process ID of the last background job - `$?` — Exit code of the last executed command - `$-` — Current shell options (flags like `e`, `u`, `x`) ```bash # Example: Check exit code, get last background PID ls /nonexistent 2>/dev/null echo "Exit code: $?" # Output: Exit code: 2 sleep 10 & echo "Background job PID: $!" # Example: Check if error handling is enabled bash -e -c 'echo $-' # Includes 'e' for set -e ``` ## Scope and Environment Variables are **global by default** in bash. Use `local` inside functions to create function-scoped variables. ```bash x=10 # Global variable increment() { x=$((x + 1)) # Modifies global x local y=5 # Local to this function echo "In function: x=$x, y=$y" } increment echo "After function: x=$x" # x is 11 # echo $y # Error: y is undefined ``` Environment variables (uppercase by convention) are inherited by child processes. Export them with `export`. ```bash # Define local variable (not inherited) DB_USER="admin" # Export to make it available to child processes export DB_PASS="secret123" # Child process can read DB_PASS python script.py # Script sees DB_PASS in os.environ # Child process cannot read DB_USER # python -c 'import os; print(os.getenv("DB_USER"))' # Returns None ```