Main index

Introducing UNIX and Linux


Advanced shell programming

Overview
Sending and trapping signals
      Signal names
Functions
Aliases
The 'exec' mechanism
The 'eval' mechanism
Sending data across networks
      Sending printable characters
      Splitting files
Makefiles
Safe programming
Setting up a terminal
More on files
Miscellaneous utilities
Summary
Exercises

Functions

The shell supports functions, which are a way of grouping commands together in a non-trivial manner without needing to write a new shell script. In complexity, functions lie between a straightforward pipe (or similar shell command) and a script.

To create a function, you first of all choose a name for a function, then enter that name, followed by (), followed by a shell command enclosed in braces. For example, a simple function myls, which performs ls -l $HOME, might be defined thus:

myls() ls -l $HOME

You must separate the braces from the function definition by blanks. To execute a function, simply type its name:

myls

A function can only be used by the shell in which it has been defined, and subshells or child processes cannot use it. A function will use the environment of the current shell (so that you need not export variables the function may use).

Worked example

Write a function myusage to display the total disk used by your home directory, preceded by a message reminding you of that directory's pathname.
Solution: Standard syntax for defining a function is followed. To find the disk usage, du is used; the output from du with option -s consists of two fields: the size of the directory that is its argument, and the name of the directory. Use cut to isolate the size. The output from du thus piped to cut will print the size of your home directory on standard output.

myusage() {
> printf "Directory %s uses " $HOME
> du -s $HOME | cut -f 1
> }

You may be wondering why functions are needed - at first sight, they may appear an added complication to the shell, and duplicate the purpose of executable shell scripts. However, there are some operations which cannot be performed by a script. Consider writing a command to alter the value of a variable in the current shell. If it is implemented as a shell script, running the command involves creating a child process whose parent is the current shell. Any change in that variable's value will be done by the child process. However, there is no way that the child process can communicate the new value back to its parent, and the variable's value in the current shell thus remains unchanged. A function, however, would be executed by the current shell without sparking a child process, and could therefore be used successfully.

Having defined one or more functions, you may wish to run a command without looking up the function definitions. You may, for instance, have a shell script that runs a command called myls. You would not wish the command run by the shell script that was called myls to be confused with the function called myls. Since a function is not the name of a file, you cannot use the value of PATH to perform the disambiguation.

As a simple example, supposing you had called the function above ls instead of myls. Then, to run the original utility called ls, simply prefix the command with command:

command ls

The effect of command is identical to typing a command not preceded by command, except that user-defined functions are not looked up. Functions can be defined interactively, or within a script, in which case they can be used from within that script only (unless the script is run using dot (.)).

Another reason for using functions is efficiency. Executing a function involves the shell in less work because it does not have to create a new process. It can also be argued that functions are easier to understand than shell scripts. One common function that many users define, in order to speed up their sessions, is ll:

ll() { ls -l }

If you wish to exit from a function before the end you should use return - this is equivalent to the use of exit to leave a shell script early.


Copyright © 2002 Mike Joy, Stephen Jarvis and Michael Luck