191

I know that when you are on shell, the only commands that can be used are the ones that can be found on some directory set on PATH. Even I don't know how to see what dirs are on my PATH variable (and this is another good question that could be answered), what I'd like to know is:

I come to shell and write:

$ lshw

I want to know a command on shell that can tell me WHERE this command is located. In other words, where this "executable file" is located?

Something like:

$ location lshw
/usr/bin
pppery
  • 3,731
  • 22
  • 33
  • 46
Gabriel L. Oliveira
  • 3,922
  • 6
  • 31
  • 40

9 Answers9

262

If you're using Bash or zsh, use this:

type -a lshw

This will show whether the target is a builtin, a function, an alias or an external executable. If the latter, it will show each place it appears in your PATH.

bash$ type -a lshw
lshw is /usr/bin/lshw
bash$ type -a ls
ls is aliased to `ls --color=auto'
ls is /bin/ls
bash$ zsh
zsh% type -a which
which is a shell builtin
which is /usr/bin/which

In Bash, for functions type -a will also display the function definition. You can use declare -f functionname to do the same thing (you have to use that for zsh, since type -a doesn't).

Dennis Williamson
  • 346,391
  • 90
  • 374
  • 439
  • 1
    Thank everybody who answered, but this answer was the most exciting! Thank you! I was thinking that I'm crazy, because I defined (a long time ago) a way to do this: 'update', and this has been doing 'apt-get update; apt-get dist-upgrade' for me. But for now, I was trying to find some update.sh file somewhere, and I couldn't find it. That's why I started this question. But now, using 'type -a update' I found that this was just an alias defined on my .bashrc located on my ~home. Really thank you. – Gabriel L. Oliveira May 20 '10 at 13:36
  • 1
    @Gabriel: If you're not familiar with `locate` it can help find files. It uses a database that's maintained by `updatedb` which is run from a cron job. Since `locate` searches a database rather than the whole filesystem it's much faster than `find` (which could be used as a last resort). – Dennis Williamson May 20 '10 at 14:10
  • Thank you. I'll study this tool, and see how updatedb is scheduled to run on Ubuntu's cronjob. – Gabriel L. Oliveira May 20 '10 at 15:58
  • Sometimes `type -a` can be confusing. e.g. in case of `nvm` which is a bash function I needed to do: `type -a nvm | head -n1` to find out what exactly is `nvm`. – Marinos An Oct 02 '19 at 12:28
  • @MarinosAn: For functions, `type -a` outputs the function definition as well as the type of executable. The risk with using `head` is that in the case of names with more than one type, the additional types wouldn't be output. You might want to look at `type -t`. – Dennis Williamson Oct 02 '19 at 12:44
  • Not a script-friendly command. It can return one or more lines, depending on whether there is an alias with that name, so you can't just do `ABS_PATH_TO_CMD=$(type -a cmd)`, you have to parse the output. But a `whereis -b cmd | awk '{print $2}'` seems to work fine for script purposes. – Hi-Angel Nov 25 '20 at 13:15
  • 1
    @Hi-Angel: Try `type -p`. – Dennis Williamson Jun 27 '22 at 21:47
91

Like this:

which lshw

To see all of the commands that match in your path:

which -a lshw 
JayRizzo
  • 3,234
  • 3
  • 33
  • 49
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • 8
    also which -a lshw to see all of the commands that match in your path. – AlG May 19 '10 at 20:25
  • I believe this only works with commands (executables on the $PATH), not functions. – Olivier Lacan Dec 08 '15 at 23:36
  • `which` is problematic because there are multiple implementations, many of which do entirely the wrong thing, and others of which seem to work fine, but have odd surprises. You should prefer `type` instead. – tripleee Mar 25 '19 at 16:30
  • 1
    Doesn't work for aliases and bash functions. At least on ubuntu. Better use `type -a lshw` – Marinos An Oct 02 '19 at 12:30
22

PATH is an environment variable, and can be displayed with the echo command:

echo $PATH

It's a list of paths separated by the colon character ':'

The which command tells you which file gets executed when you run a command:

which lshw

sometimes what you get is a path to a symlink; if you want to trace that link to where the actual executable lives, you can use readlink and feed it the output of which:

readlink -f $(which lshw)

The -f parameter instructs readlink to keep following the symlink recursively.

Here's an example from my machine:

$ which firefox
/usr/bin/firefox

$ readlink -f $(which firefox)
/usr/lib/firefox-3.6.3/firefox.sh
hasen
  • 161,647
  • 65
  • 194
  • 231
5
~$ echo $PATH
/home/jack/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
~$ whereis lshw
lshw: /usr/bin/lshw /usr/share/man/man1/lshw.1.gz
Jack
  • 20,735
  • 11
  • 48
  • 48
  • Some elaboration might be helpful to future readers: to find the binary you gotta use `-b` option, and then you can combine it with `awk` to get the path. So, something like: `whereis -b ack | awk '{print $2}'` – Hi-Angel Nov 25 '20 at 13:11
3

In the TENEX C Shell, tcsh, one can list a command's location(s), or if it is a built-in command, using the where command e.g.:

tcsh% where python
/usr/local/bin/python
/usr/bin/python

tcsh% where cd
cd is a shell built-in
/usr/bin/cd
Pierz
  • 7,064
  • 52
  • 59
  • There was a time when `tcsh` was popular but that was before open source Bourne-compatible shells became widely available. – tripleee Mar 25 '22 at 19:44
3

An alternative to type -a is command -V

Since most of the times I am interested in the first result only, I also pipe from head. This way the screen will not flood with code in case of a bash function.

command -V lshw | head -n1
Marinos An
  • 9,481
  • 6
  • 63
  • 96
3

TLDR Answer

Use: whereis -b lshw.

Explanation

Use the whereis command. From the man page:

whereis - locate the binary, source, and manual page files for a command

Commonly-Used Switches

In addition, you can specify what you're looking for:

  • whereis -b packagename : Source for location of binaries.
  • whereis -m packagename : Source for location of manuals.
  • whereis -s packagename : Source for location of source code.

In your case, since you're looking for the binary, you'll want: whereis -b lshw.

There are other switches with this command, check them out at the man page. If there is no file associated with a packagename, you'll see a blank line.

Examples

Here's some real world use:

holdoffhunger@tower:~$ whereis grep
grep: /bin/grep /usr/share/man/man1/grep.1.gz /usr/share/man/man1/grep.1posix.gz

holdoffhunger@tower:~$ whereis -m grep
grep: /usr/share/man/man1/grep.1.gz /usr/share/man/man1/grep.1posix.gz

holdoffhunger@tower:~$ whereis -s grep
grep:
HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
1

The Korn shell, ksh, offers the whence built-in, which identifies other shell built-ins, macros, etc. The which command is more portable, however.

mpez0
  • 2,815
  • 17
  • 12
1

In zsh (in my case the current version is 5.9), you can check the directory of some command using = as prefix. For example, if you want to know where is located the mkdir command you can use:

$> ls -l =mkdir
-rwxr-xr-x 1 root root 76216 Jun 14 20:49 /usr/bin/mkdir

Or more simplificated:

$> echo =mkdir
/usr/bin/mkdir

Note: This method only works for commands that are available in your current shell according to your $PATH environment variable. So, if your $PATH has the value "/home/user/bin:/usr/bin:/usr/local/bin" only the commands under those 3 paths will be available.

Edgar Magallon
  • 556
  • 2
  • 7
  • 15