How does Unix search for executable files?

48

14

When a file is executed, how does Unix search for it? If there are multiple executable files in PATH with the same name, which one is preferred? Is the current directory included in the search when a file is executed?

Suppose there is a file with name executable.sh in the current directory. Would that work if it is executed $ executed and . is not part of the PATH?

Leonid

Posted 2011-01-28T16:28:54.587

Reputation: 481

mentioning which <executable> command will be useful in this thread.

– Accountant م – 2019-04-18T14:35:35.067

Answers

47

The $PATH is searched from beginning to end, with the first matching executable being run. So directories at the beginning of $PATH take precedence over those that come later. Executables in the current directory (.) are only executed if . is in $PATH (which it usually isn't). There is no implicit inclusion of the current directory in the search path.

coneslayer

Posted 2011-01-28T16:28:54.587

Reputation: 7 494

It's weird that, my $PATH don't contains ., but it seems would search from current dir first, before check dirs defined in $PATH itself. – Eric Wang – 2017-02-03T16:24:30.557

19

For files in the current directory, you will want to precede them with ./, so the command would become ./executable.sh. You should never have . in your PATH as it poses a security risk, among other problems.

Directories that come first in the PATH and searched first.

The overall order for searching is like this if I remember correctly:

  • aliases

  • exported functions

  • built-in shell commands

  • scripts and binaries in your PATH

John T

Posted 2011-01-28T16:28:54.587

Reputation: 149 037

3+1 for the order of searching. Would be nice if you could remember the source of information :) – twan163 – 2016-12-14T18:08:28.017

7I'd add the hash - remember bash (and maybe other shells) keep a hash of recently used commands to make finding them easier. Sometimes you have to purge the cache (using hash -r) if you change your PATH or program locations. – Rich Homolka – 2011-01-28T23:34:31.617

8

Though this has been answered well by some others, I'd like to add some thoughts:

1) PATH is only consulted if the executable invoked has no path elements in it. somecommand would be looked up in $PATH, ./somecommand or /usr/bin/somecommand, or ../../bin/somecommand just use directory rules, not PATH

If there are multiple executable files in PATH with the same name which one is preferred?

It stops at the first one it finds, reading $PATH left to right.

Is current directory included in the search when file is executed?

If the current directory is in PATH then it is searched. Remember that an empty directory in PATH includes the current directory. e.g. PATH=:/usr/bin (leading empty) PATH=/usr/bin: (trailing empty) and PATH=/usr/bin::/bin (middle empty) will all effectively include current working directory.

Suppose there is a file with name executable.sh in a current directory. Would that work if it is executed $ executed and . is not part of the PATH?

It would never find it by searching PATH. If current dir is not in PATH, it won't find it by a PATH lookup.

That said (and sorry to add confusion) if there was an alias or function that ran the command, it would be run. Or if your shell had a location cache, and the executable was in the cache, it may find it. So, it will never find it in PATH, but it may be run by other means.

Rich Homolka

Posted 2011-01-28T16:28:54.587

Reputation: 27 121

Thanks for the cache note, it almost drive me crazy that the old executable in /usr/bin/ is still invoked not the new one in /usr/local/bin, however it is on the left in the $PATH till I logged out, and logged in again. – Accountant م – 2019-04-18T14:23:30.797

1@theaccountant in bash you can do ‘hash -r’ to clear the shell cache – Rich Homolka – 2019-04-18T18:28:08.083

4

To see what your path currently is just type echo $PATH, or printenv PATH.

Then you'll know the order of searching. If you have multiple files with the same name, just run which ____ to see.

Ex.

system#> which grep

/usr/bin/grep

a cool way to find files that work like your target is to use apropos:

apropos grep

bzgrep (1) - search possibly bzip2 compressed files for a regular expression

egrep (1) - print lines matching a pattern

fgrep (1) - print lines matching a pattern

grep (1) - print lines matching a pattern

and so on...

mbb

Posted 2011-01-28T16:28:54.587

Reputation: 2 206

@grawity Could you expand on that? – WinEunuuchs2Unix – 2018-11-09T01:09:03.373

2Oh yeah -- I forgot the whereis function to find ALL instances of a file:

whereis grep

– mbb – 2011-01-28T16:42:02.407

grep: /bin/grep /usr/bin/grep /usr/share/man/man1/grep.1.gz – mbb – 2011-01-28T16:42:49.333

whereis uses a hardcoded list of locations, not $PATH. – user1686 – 2011-01-28T20:45:17.853

-2

@coneslayer- The default order of finding executable is the current path, built in commands and then the $PATH. So if a function named executable already exists in the pwd, then that is executed.if not then the precedence searches for built in commands of shell and then $PATH

proc

Posted 2011-01-28T16:28:54.587

Reputation: 1

If you were talking about the Thompson shell, the Mashey shell, or some other fossilized holdover from 40 years ago, you might be right.   But no current, mainstream Unix shell searches the current directory automatically. – Scott – 2018-07-12T17:36:43.420

@Scott So the default search path for a command is first built in and then $PATH and searches the CWD only if I give ./ ? Am i right? – proc – 2018-07-12T17:42:35.683

Well, aliases, functions, and builtins.  Then, if you specify a path with the command (including ./), it searches that directory only; otherwise, it searches $PATH. – Scott – 2018-07-12T17:47:29.250