24.2. Local Variables

What makes a variable local?

local variables

A variable declared as local is one that is visible only within the block of code in which it appears. It has local scope. In a function, a local variable has meaning only within that function block. [1]


Example 24-12. Local variable visibility

   1 #!/bin/bash
   2 # ex62.sh: Global and local variables inside a function.
   3 
   4 func ()
   5 {
   6   local loc_var=23       # Declared as local variable.
   7   echo                   # Uses the 'local' builtin.
   8   echo "\"loc_var\" in function = $loc_var"
   9   global_var=999         # Not declared as local.
  10                          # Therefore, defaults to global. 
  11   echo "\"global_var\" in function = $global_var"
  12 }  
  13 
  14 func
  15 
  16 # Now, to see if local variable "loc_var" exists outside the function.
  17 
  18 echo
  19 echo "\"loc_var\" outside function = $loc_var"
  20                                       # $loc_var outside function = 
  21                                       # No, $loc_var not visible globally.
  22 echo "\"global_var\" outside function = $global_var"
  23                                       # $global_var outside function = 999
  24                                       # $global_var is visible globally.
  25 echo				      
  26 
  27 exit 0
  28 #  In contrast to C, a Bash variable declared inside a function
  29 #+ is local ONLY if declared as such.

Caution

Before a function is called, all variables declared within the function are invisible outside the body of the function, not just those explicitly declared as local.
   1 #!/bin/bash
   2 
   3 func ()
   4 {
   5 global_var=37    #  Visible only within the function block
   6                  #+ before the function has been called. 
   7 }                #  END OF FUNCTION
   8 
   9 echo "global_var = $global_var"  # global_var =
  10                                  #  Function "func" has not yet been called,
  11                                  #+ so $global_var is not visible here.
  12 
  13 func
  14 echo "global_var = $global_var"  # global_var = 37
  15                                  # Has been set by function call.

Note

As Evgeniy Ivanov points out, when declaring and setting a local variable in a single command, apparently the order of operations is to first set the variable, and only afterwards restrict it to local scope. This is reflected in the return value.

   1 #!/bin/bash
   2 
   3 echo "==OUTSIDE Function (global)=="
   4 t=$(exit 1)
   5 echo $?      # 1
   6              # As expected.
   7 echo
   8 
   9 function0 ()
  10 {
  11 
  12 echo "==INSIDE Function=="
  13 echo "Global"
  14 t0=$(exit 1)
  15 echo $?      # 1
  16              # As expected.
  17 
  18 echo
  19 echo "Local declared & assigned in same command."
  20 local t1=$(exit 1)
  21 echo $?      # 0
  22              # Unexpected!
  23 #  Apparently, the variable assignment takes place before
  24 #+ the local declaration.
  25 #+ The return value is for the latter.
  26 
  27 echo
  28 echo "Local declared, then assigned (separate commands)."
  29 local t2
  30 t2=$(exit 1)
  31 echo $?      # 1
  32              # As expected.
  33 
  34 }
  35 
  36 function0

24.2.1. Local variables and recursion.

Local variables are a useful tool for writing recursive code, but this practice generally involves a great deal of computational overhead and is definitely not recommended in a shell script. [6]


Example 24-15. Recursion, using a local variable

   1 #!/bin/bash
   2 
   3 #               factorial
   4 #               ---------
   5 
   6 
   7 # Does bash permit recursion?
   8 # Well, yes, but...
   9 # It's so slow that you gotta have rocks in your head to try it.
  10 
  11 
  12 MAX_ARG=5
  13 E_WRONG_ARGS=85
  14 E_RANGE_ERR=86
  15 
  16 
  17 if [ -z "$1" ]
  18 then
  19   echo "Usage: `basename $0` number"
  20   exit $E_WRONG_ARGS
  21 fi
  22 
  23 if [ "$1" -gt $MAX_ARG ]
  24 then
  25   echo "Out of range ($MAX_ARG is maximum)."
  26   #  Let's get real now.
  27   #  If you want greater range than this,
  28   #+ rewrite it in a Real Programming Language.
  29   exit $E_RANGE_ERR
  30 fi  
  31 
  32 fact ()
  33 {
  34   local number=$1
  35   #  Variable "number" must be declared as local,
  36   #+ otherwise this doesn't work.
  37   if [ "$number" -eq 0 ]
  38   then
  39     factorial=1    # Factorial of 0 = 1.
  40   else
  41     let "decrnum = number - 1"
  42     fact $decrnum  # Recursive function call (the function calls itself).
  43     let "factorial = $number * $?"
  44   fi
  45 
  46   return $factorial
  47 }
  48 
  49 fact $1
  50 echo "Factorial of $1 is $?."
  51 
  52 exit 0

Also see Example A-15 for an example of recursion in a script. Be aware that recursion is resource-intensive and executes slowly, and is therefore generally not appropriate in a script.

Notes

[1]

However, as Thomas Braunberger points out, a local variable declared in a function is also visible to functions called by the parent function.

   1 #!/bin/bash
   2 
   3 function1 ()
   4 {
   5   local func1var=20
   6 
   7   echo "Within function1, \$func1var = $func1var."
   8 
   9   function2
  10 }
  11 
  12 function2 ()
  13 {
  14   echo "Within function2, \$func1var = $func1var."
  15 }
  16 
  17 function1
  18 
  19 exit 0
  20 
  21 
  22 # Output of the script:
  23 
  24 # Within function1, $func1var = 20.
  25 # Within function2, $func1var = 20.

This is documented in the Bash manual:

"Local can only be used within a function; it makes the variable name have a visible scope restricted to that function and its children." [emphasis added] The ABS Guide author considers this behavior to be a bug.

[2]

Otherwise known as redundancy.

[3]

Otherwise known as tautology.

[4]

Otherwise known as a metaphor.

[5]

Otherwise known as a recursive function.

[6]

Too many levels of recursion may crash a script with a segfault.
   1 #!/bin/bash
   2 
   3 #  Warning: Running this script could possibly lock up your system!
   4 #  If you're lucky, it will segfault before using up all available memory.
   5 
   6 recursive_function ()		   
   7 {
   8 echo "$1"     # Makes the function do something, and hastens the segfault.
   9 (( $1 < $2 )) && recursive_function $(( $1 + 1 )) $2;
  10 #  As long as 1st parameter is less than 2nd,
  11 #+ increment 1st and recurse.
  12 }
  13 
  14 recursive_function 1 50000  # Recurse 50,000 levels!
  15 #  Most likely segfaults (depending on stack size, set by ulimit -m).
  16 
  17 #  Recursion this deep might cause even a C program to segfault,
  18 #+ by using up all the memory allotted to the stack.
  19 
  20 
  21 echo "This will probably not print."
  22 exit 0  # This script will not exit normally.
  23 
  24 #  Thanks, Stéphane Chazelas.