I need to find the path of a given program on the PATH
using a shell script. The path must be the actual full path of the program, which can be passed later to one of the exec*
functions, which does not search the PATH
itself, e.g. execv
.
There are programs like kill
, which are available as an actual program and a shell built-in at the same time. If this is case, I need the full path to the actual program.
There are several utilities that can find a program on the PATH
as specified in Section 2.9.1.1, Command Search and Execution of the POSIX standard.
There is which
, which is not part of any standard. It can be a regular program on some systems, whereas some shells provide it is a builtin. It seems to be available on most systems and shells, but the shells with a builtin version, also just return the name of the built-in instead of the path to the executable. Also it is not standardized in any way and may return any output and take different options.
bash# which kill
/usr/bin/kill
dash# which kill
/usr/bin/kill
fish# which kill
/usr/bin/kill
mksh# which kill
/usr/bin/kill
tcsh# which kill
kill: shell built-in command.
zsh# which kill
kill: shell built-in command
There is whence
, which is a built-in of a few shells. But not available on many shells. It will too return the name of the built-in instead of the path to program. A -p
may be passed to whence to change this behavior.
bash# whence kill
bash: whence: command not found
dash# whence kill
dash: 1: whence: not found
fish# whence kill
fish: Unknown command 'whence'
mksh# whence kill
kill
mksh# whence -p kill
/usr/bin/kill
tcsh# whence kill
whence: Command not found.
zsh# whence kill
kill
zsh# whence -p kill
/usr/bin/kill
There is the command
builtin specified by POSIX:2008. Unfortunately it also searches for regular commands and built-ins and will return the name of the built-in instead of the path to the program shadowed by a built-in of the same name. Some old shells haven't implemented it yet.
bash# command -v kill
kill
dash# command -v kill
kill
fish# command -v kill
/usr/bin/kill
mksh# command -v kill
kill
tcsh# command -v kill
command: Command not found.
zsh# command -v kill
kill
enable
is specified in POSIX or not, but if it is, you could useenable -n which
to disable the shell built-in forwhich
.realpath
enable
is only provided bybash
andzsh
type -p
. Both bash and dash let you saycommand
command to run an actual executable even if there is a function or builtin with the same name.command
skips functions (and aliases) but NOT builtins, as the Q correctly says. And you can't always use a shebang because there is no path that gets any given shell, or even some POSIX shell, on all systems.