Chapter 23. Functions

Table of Contents
23.1. Complex Functions and Function Complexities
23.2. Local Variables and Recursion

Like "real" programming languages, Bash has functions, though in a somewhat limited implementation. A function is a subroutine, a code block that implements a set of operations, a "black box" that performs a specified task. Wherever there is repetitive code, when a task repeats with only slight variations, then consider using a function.

function function_name {
command...
}

or

function_name () {
command...
}

This second form will cheer the hearts of C programmers (and is more portable).

As in C, the function's opening bracket may optionally appear on the second line.

function_name ()
{
command...
}

Functions are called, triggered, simply by invoking their names.

Example 23-1. Simple function

#!/bin/bash

funky ()
{
  echo "This is a funky function."
  echo "Now exiting funky function."
} # Function declaration must precede call.

  # Now, call the function.

funky

exit 0

The function definition must precede the first call to it. There is no method of "declaring" the function, as, for example, in C.
# f1
# Will give an error message, since function "f1" not yet defined.

# However...

	  
f1 ()
{
  echo "Calling function \"f2\" from within function \"f1\"."
  f2
}

f2 ()
{
  echo "Function \"f2\"."
}

f1  # Function "f2" is not actually called until this point,
    # although it is referenced before its definition.
    # This is permissable.
    
# Thanks, S.C.

It is even possible to nest a function within another function, although this is not very useful.
f1 ()
{

  f2 () # nested
  {
    echo "Function \"f2\", inside \"f1\"."
  }

}  

# f2
# Gives an error message.

f1  # Does nothing, since calling "f1" does not automatically call "f2".
f2  # Now, it's all right to call "f2",
    # since its definition has been made visible by calling "f1".

# Thanks, S.C.

Function declarations can appear in unlikely places, even where a command would otherwise go.
ls -l | foo() { echo "foo"; }  # Permissable, but useless.



if [ "$USER" = bozo ]
then
  bozo_greet ()   # Function definition embedded in an if/then construct.
  {
    echo "Hello, Bozo."
  }
fi  

bozo_greet        # Works only for Bozo, and other users get an error.



# Something like this might be useful in some contexts.
NO_EXIT=1   # Will enable function definition below.

[[ $NO_EXIT -eq 1 ]] && exit() { true; }     # Function definition in an "and-list".
# If $NO_EXIT is 1, declares "exit ()".
# This disables the "exit" builtin by aliasing it to "true".

exit  # Invokes "exit ()" function, not "exit" builtin.

# Thanks, S.C.