Loading shell functions

First of all some thoughts about when and where to load shell functions.

Configuration files: In principle shell functions can be defined in one of the configuration files (.profile, .bashrc etc.), so that the shell loads them automatically. However, it doesn't make sense to load all existing functions on every shell start. Some (such as bash completion) only apply to interactive shells, others are only required by specific scripts. In non-interactive shells one shouldn't pre-define any functions at all, but provide each script with a clean environment and load required functions in the script, using file or source file. In doing so, it is also recommended to avoid absolute paths, which cause strong coupling with the system environment and reduce portability. A better way is to use the shell's search facility.

Search: If the parameter supplied with file or source file represents a simple name, the shell searches the directories contained in $PATH for a file of the given name. The first one found will be sourced. The shell expects it to define the respective function; if that isn't the case, it tries to call it as a script. To make use of the search facility, each function has to be put in a separate file named after the function. The file may contain other things as well, like auxiliary functions, but such side effects should be restricted to a minimum. The function definitions are concentrated in a few directories, and the absolute paths of the directories are added to the setting of $PATH, as usual separated by :. All this can be done in a profile file. Afterwards functions can be loaded by simply supplying their name, i.e. by source functionname.

Autoload: The Kornshell provides an additional autoload mechanism. To use it, one does like described above and additionally sets the exported variable FPATH to a list of the function directories. In other words, $FPATH must be a subset of $PATH. If these conditions are met, ksh does a search for any function being called but not yet defined, and loads it automatically if found. No explicit source is required.

While this is quite convenient, it can also have its drawbacks. If a function func is called exclusively in the form $(func parameter...) (i.e., in subshells), it will be looked up and loaded on every call, which is inefficient. [1] In this case it's better to source the function explicitly once at the start of the script. The definition will then automatically be passed to subshells. Note, however, that this must happen exactly once. If func is already defined, source func will be a call instead of a redefinition. To make sure, either provide the absolute path of the function file instead of the name, or prepend a condition:

typeset +f func >/dev/null || source func

[1] In ksh93t there will be a more efficient command substitution ${command}, which will run the command in the current shell (thanks to David Korn).

Created 2011-08-11 by mopcoge