8.2. Local vs Global#

8.2.1. Common Pitfalls#

1. Forgetting local and accidentally modifying globals

# Bad: Silently changes global state
process_data() {
  temp=$1      # Overwrites global temp
  result=$temp  # Sets global result
}

# Good: Protect the global scope
process_data() {
  local temp=$1
  local result=$temp
}

2. Relying on variable scope instead of being explicit

# Fragile: Works now but risky
func_a() {
  x=10
  func_b
  echo $x  # Depends on func_b not changing x
}

# Better: Be explicit
func_a() {
  local x=10
  func_b
  echo $x  # Now safe: func_b can't affect x
}

3. Shadowing without realizing it

# Surprising behavior
name="global"
change_name() {
  local name="local"  # Shadowing not obvious
}
change_name
echo $name  # Still "global" - might surprise the reader

8.2.2. Real-World Example: Encapsulation#

#!/bin/bash

# Global configuration
username="admin"
password=""

# Function that uses local variables for safety
validate_credentials() {
  local input_user=$1
  local input_pass=$2
  local temp_hash
  
  # temp_hash is local to this function only
  temp_hash=$(echo -n "$input_pass" | md5sum | cut -d' ' -f1)
  
  if [[ "$input_user" == "$username" ]]; then
    echo "User found"
    return 0
  else
    echo "User not found"
    return 1
  fi
}

# Initialize password (global)
set_password() {
  password=$1  # Sets global password
}

# Call function
set_password "secret123"
validate_credentials "admin" "secret123"

Best practice: Use local variables in functions to avoid accidentally modifying global state.

8.2.3. Nested Function Calls and Scope#

Local variables are visible to functions called from within the function.

8.2.3.1. Scope Chain#

#!/bin/bash

outer_var="outer"

func_a() {
  local func_a_var="in func_a"
  echo "func_a: outer_var=$outer_var, func_a_var=$func_a_var"
  func_b
}

func_b() {
  # Can see outer_var (global) and func_a_var (from caller)
  echo "func_b: outer_var=$outer_var, func_a_var=$func_a_var"
  local func_b_var="in func_b"
  func_c
}

func_c() {
  # Can see outer_var and func_a_var, but NOT func_b_var
  echo "func_c: outer_var=$outer_var, func_a_var=$func_a_var"
  # func_b_var is not visible here
}

func_a

# Output:
# func_a: outer_var=outer, func_a_var=in func_a
# func_b: outer_var=outer, func_a_var=in func_a
# func_c: outer_var=outer, func_a_var=in func_a

Local variables from parent functions are visible, but siblings’ locals are not.

8.2.4. Shadowing: Local Variables with Same Names#

When a function declares a local variable with the same name as a global, the local shadows the global within that function.

8.2.4.1. Shadowing Example#

#!/bin/bash

name="Alice"

process() {
  local name="Bob"  # Shadows the global 'name'
  echo "In function: $name"
}

echo "Before: $name"
process
echo "After: $name"

# Output:
# Before: Alice
# In function: Bob
# After: Alice

# The global 'name' is unchanged

8.2.5. Local Variables with local Keyword#

Use the local keyword to create function-scoped variables. Local variables are visible only within the function and any functions it calls.

8.2.5.1. Local Variable Scope#

#!/bin/bash

counter=0  # Global

increment() {
  local counter=100  # Local: shadows the global
  counter=$((counter + 1))
  echo "In function: counter=$counter"
}

echo "Before: counter=$counter"
increment
echo "After: counter=$counter"

# Output:
# Before: counter=0
# In function: counter=101
# After: counter=0

The local declaration creates a variable that exists only within the function’s scope.

8.2.6. Global Variables and Functions#

In bash, variables are global by default. Any variable set inside a function is accessible everywhere in the script.

8.2.6.1. Global Variable Behavior#

#!/bin/bash

# Global variable
message="Global message"

show_message() {
  echo "In function: $message"
  message="Function changed this"
}

echo "Before: $message"
show_message
echo "After: $message"

# Output:
# Before: Global message
# In function: Global message
# After: Function changed this

This can lead to unexpected behavior: the function modified the global variable.