## 27.9. Which One Will bash Use?

bash, like all shells, performs a series of steps when evaluating a command line. (Sorry, we don't cover all of the Unix shells; we explain bash because it's one of the most common. For other shells, check their manual pages.) This article takes a closer look at how you can control one part of those steps in bash: whether the shell will choose a shell function (Section 29.11), a built-in command ( Section 1.9), or an external command (Section 1.9).

Let's say that you want to write shell functions named cd, pushd, and popd. They will run the shell's built-in cd, pushd, or popd command, respectively, each using the command-line arguments that were passed (via the `$@` array reference). Next they execute another shell function named setvars to do some setup in the new directory:

>     cd( ) {            pushd( ) {         popd( ) {
>       cd "$@"           pushd "$@"        popd "$@"
>       setvars           setvars           setvars
>     }                 }                 }

But which cd will bash use when you type cd: the built-in cd or your cd function? (The same question goes for pushd and popd.) Worse, what if the `cd <">$@<">` command inside the function makes bash call your cd function again, and that starts an endless loop? Well, that actually will start a loop -- and you need to know how to prevent it.

Typing command before the name of a command disables shell function lookup. bash will execute only a built-in command or an external command with that name. So, you could keep the functions from re-executing themselves by defining them this way:

>     cd( ) {                    pushd( ) {                popd( ) {
>         command cd "$@"       command pushd "$@"       command popd "$@"
>         setvars               setvars                  setvars
>     }                         }                        }

In the same way, if you don't want to run your new pushd function for some reason, here's how to use the built-in pushd once:

>     bash$ command pushd somewhere

The command command still allows bash to run an external command (from your PATH (Section 35.6)) with the name you give. To force bash to use a built-in command -- but not a shell function or an external command -- type builtin before the command name. Although bash will always choose a built-in command before an external command, you can specify the built-in echo unambiguously with:

>     builtin echo -n 'What next? '

What if you want the external echo command? The easiest way is probably to type its absolute pathname. For example, once I wanted to test four (!) different external versions of echo on a System V machine -- and not get the built-in bash version. So I typed commands like this:

>     bash$ /bin/echo hi \\ there

Finally, you can enable or disable specific built-in bash commands with the enable command. Unlike command and builtin, the effect of enable lasts until you exit the shell. The command enable -n disables one or more built-in commands; give the command names as arguments. For example, in my experiments mentioned above, I could have made sure that I'd get an external echo every time by typing this first command once:

>     bash$ enable -n echo
>     bash$ type echo
>     echo is hashed (/bin/echo)

The `-n` disables the built-in command named as the following argument. The bash type command confirms that I'll now be using the external echo. You can re-enable a disabled built-in with `enable` `command-name`. And enable -a lists the status of all bash built-ins.

-- JP

Copyright © 2003 O'Reilly & Associates. All rights reserved.