Using or Replacing Built-ins and External Commands

Problem

You want to replace a built-in command with your own function or external command, and you need to know exactly what your script is executing (e.g., /bin/echo or the built-in echo). Or you’ve created a new command and it may be conflicting with an existing external or built-in command.

Solution

Use the type and which commands to see if a given command exists and whether it is built-in or external.

# type cd
cd is a shell builtin

# type awk
awk is /bin/awk

# which cd
/usr/bin/which: no cd in (/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/
sbin:/usr/bin/X11:/usr/X11R6/bin:/root/bin)

# which awk
/bin/awk

Discussion

A built-in command is just that; it is built into the shell itself, while an external command is an external file launched by the shell. The external file may be a binary, or it may be a shell script itself, and its important to understand the difference for a couple of reasons. First, when you are using a given version of a particular shell, built-ins will always be available but external programs may or may not be installed on a particular system. Second, if you give one of your own programs the same name as a built-in, you will be very confused about the results since the built-in will always take precedence (see Naming Your Script Test). It is possible to use the enable command to turn built-in commands off and on, though we strongly recommend against doing so unless you are absolutely sure you understand what you are doing. enable -a will list all built-ins and their enabled or disabled status.

One problem with built-in commands is that you generally can’t use a -h or --help option to get usage reminders, and if a manpage exists it’s often just a pointer to the large bash manpage. That’s where the help command, which is itself a built-in, comes in handy. help displays help about shell built-ins.

# help help
help: help [-s] [pattern ...]
    Display helpful information about builtin commands. If PATTERN is
    specified, gives detailed help on all commands matching PATTERN,
    otherwise a list of the builtins is printed. The -s option
    restricts the output for each builtin command matching PATTERN to
    a short usage synopsis.

When you need to redefine a built-in you use the builtin command to avoid loops. For example:

cd () {
    builtin cd "$@"
    echo "$OLDPWD --> $PWD"
}

To force the use of an external command instead of any function or built-in that would otherwise have precedence, use enable -n, which turns off shell built-ins, or command, which ignores shell functions. For example, to use the test found in $PATH instead of the shell built-in version, type enable -n test and then run test. Or, use command ls to use the native ls command rather than any ls function you may have created.

See Also

Get bash Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.