3.6. Functions, Aliases, and the Environment

As mentioned earlier, PS1, PS2, PS3, PS4, and PROMPT_COMMAND are all stored in the Bash environment. The environment is a good place to store variables (such as the prompt strings), functions, and aliases you use frequently.

I risk censure by Unix gurus when I say this (for the crime of over-simplification), but functions are basically small shell scripts that are loaded into the environment for the purpose of efficiency. Quoting Dan: "Shell functions are about as efficient as they can be. It is the approximate equivalent of sourcing a bash/bourne shell script save that no file I/O need be done as the function is already in memory. The shell functions are typically loaded from [.bashrc or .bash_profile] depending on whether you want them only in the initial shell or in subshells as well. Contrast this with running a shell script: Your shell forks, the child does an exec, potentially the path is searched, the kernel opens the file and examines enough bytes to determine how to run the file, in the case of a shell script a shell must be started with the name of the script as its argument, the shell then opens the file, reads it and executes the statements. Compared to a shell function, everything other than executing the statements can be considered unnecessary overhead."

Aliases are simple to create:

alias d="ls --color=tty --classify"
alias v="d --format=long"
alias rm="rm -i"

Any arguments you pass to the alias are passed to the command line of the aliased command (ls in the first two cases). Note that aliases can be nested, and they can be used to make a normal unix command behave in a different way. (I agree with the argument that you shouldn't use the latter kind of aliases - if you get in the habit of relying on "rm *" to ask you if you're sure, you may lose important files on a system that doesn't use your alias.)

Functions are used for more complex program structures. As a general rule, use an alias for anything that can be done in one line. Functions differ from shell scripts in that they are loaded into the environment so that they work more quickly. As a general rule again, you would want to keep functions relatively small, and any shell script that gets relatively large should remain a shell script rather than turning it into a function. Your decision to load something as a function is also going to depend on how often you use it. If you use a small shell script infrequently, leave it as a shell script. If you use it often, turn it into a function.

To modify the behaviour of ls, you could do something like the following:

function lf
    ls --color=tty --classify $*
    echo "$(ls -l $* | wc -l) files"

It would appear that this could easily be an alias, but in fact it can't: there's a huge limitation on how aliases handle arguments, and passing the same arguments twice does not work with an alias. You can't pass them arguments at all, but they will treat any trailing text as arguments. If you type the text shown into a text file and then source that file, the function will be in your environment, and be immediately available at the command line without the overhead of a shell script mentioned previously. The usefulness of this becomes more obvious if you consider adding more functionality to the above function, such as using an if statement to execute some special code when links are found in the listing.