Command Order of Precedence
The common misconception is that the shell always searches the PATH variable to find a command. The truth is that the shell may never get to the PATH variable before it has a name match. Before confusing the issue, let’s look at a simple example. If there is an alias that reads which=’whence -a’, and you enter which pwd, the which command is never executed. The shell first finds the alias, and then subsitutes the alias for the command, and starts the search all over. From this, we know that an alias has precedence over the PATH variable. So what is the order of precedence for finding the command?
The first myth to bust is that there is a common order of precedence followed by all shells, or that all shell versions follow the same order of precedence. We will start with a generic list of the order or precedence, and then move to variations between different shells, and different shell versions. When resolving a command name, the shell goes through this order:
- If the command has an absolute or relative pathname as a prefix to the command, the shell uses this path to find the command. When you enter ./command, the ./ is a relative pathname that says the command exists in the current working directory. An absolute or relative pathname ends the search, even if the command does not exist at the specified location. Be careful with pathnames, as there is no path to a shell built-in command. Thus, /bin/pwd executes the Bourne Shell version of the pwd command and not the built-in pwd command. As mentioned in the previous post, the built-in command may have different options, or sutle behavior differences.
- KornShell enforces a rule that there are certain keywords that take precedence over all other names. These keywords are: !, [[, case, for, function, if, select, time, until, and while. Bash does not enforce this rule. Consequently you can create an alias for a keyword, and bash executes the alias. You can use the whence -v command to check if a name is a keyword, for bash use the type -a command.
- The shell next checks to see if there is an alias with the same name as the command. Shell performs a command substitution and then reparses the command line. Try the following tests, and see what happens:
alias ls=’ls -a’
ls
ls -l
alias dir=’ls -l’
dir
unalias ls
dir
unalias dirWhile KornShell ignores an alias of a keyword, it does allow you to create an alias to a keyword. For example, you can write
alias spin=’while’
Of course, bash also allows an alias to a keyword. It just doesn’t protect keywords from being aliased.
- Certain built-in commands are special, and KornShell make sure that these built-in commands have priority over functions. Yet, you can alias them to another command. These special built-ins are: . (dot), :, alias, break, continue, eval, exec, exit, export, login, newgrp, readonly, return, set, shift, trap, typeset, unalias, and unset. As with keywords, bash does not protect these built-in commands from functions with the same name.
- Shells treat functions like commands, and functions are part of the environments name space. While the set command will show you any local or exported functions, you can get a list of function with the typeset -f command. In ksh, the functions “command” is an alias for typeset -f.
- For KornShell the “non-special” built-in commands, and all built-in commands for bash, take precedence over any command by the same name.
- To improved performance, ksh offers a feature called the “tracked alias.” The first time you use a command that involves searching the PATH variable, ksh saves the path as a tracked alias. The next time you execute the command it doesn’t need to search the PATH variable.
- If there are no other matches, then shell search for the command by traversing the directories in the PATH variable. One directory at a time until it finds the command. With Linx. the first time through is the most I/O intensive. If the directory is accessed on a regular basis, the Kernel does keep a copy in memory to avoid unnecessary disk I/O.
- KornShell supports the concept of a function libraries, with the FPATH variable contain a list of directories to search fot the function.
As you can see, searching for a command is a little more complicated than just searching the PATH variable. To avoid any conflicts, the safe rule is to make all command and function names unique.


