如何找到某个命令的目录?

191

我知道当你在shell中时,唯一可以使用的命令是可以在PATH设置的某个目录中找到的命令。

即使我不知道如何查看我的PATH变量中有哪些目录(这是另一个很好的问题可以回答),但我想知道的是:

我进入shell并写入:

$ lshw

我想知道在shell中有哪个命令可以告诉我这个命令的位置。换句话说,这个“可执行文件”在哪里?

类似于:

$ location lshw
/usr/bin
9个回答

263

如果您正在使用Bash或zsh,请使用以下内容:

type -a lshw

这将显示目标是内置函数、函数、别名还是外部可执行文件。如果是后者,它将显示它在您的 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

Bash中,对于函数type -a也会显示函数定义。您可以使用declare -f functionname来完成相同的操作(对于zsh,您必须使用该命令,因为type -a不会显示函数定义)。


1
感谢所有回答的人,但这个答案最令人兴奋!谢谢!我一直在想我是不是疯了,因为我很久以前就定义了一种方法来做这件事:'update',这一直为我执行 'apt-get update; apt-get dist-upgrade'。但现在,我正在尝试找到某个 update.sh 文件,但我找不到它。这就是我发起这个问题的原因。但现在,使用 'type -a update',我发现这只是一个别名,定义在我的 .bashrc 中,位于我的 ~home 目录下。真的非常感谢。 - Gabriel L. Oliveira
1
@Gabriel:如果你不熟悉locate命令,它可以帮助你查找文件。它使用由updatedb维护的数据库,该数据库是从cron作业运行的。由于locate搜索的是数据库而不是整个文件系统,因此比find快得多(后者只能作为最后一招)。 - Dennis Williamson
谢谢,我会研究这个工具,并查看如何安排updatedb在Ubuntu的cronjob上运行。 - Gabriel L. Oliveira
@MarinosAn:对于函数,type -a 输出函数定义以及可执行文件类型。使用 head 的风险在于,在名称具有多个类型的情况下,其他类型不会被输出。您可能需要查看 type -t - Dennis Williamson
1
@Hi-Angel:尝试使用 type -p - Dennis Williamson
显示剩余2条评论

92

像这样:

which lshw

要查看与您的路径匹配的所有命令:

which -a lshw 

8
同时,使用命令“-a lshw”可以查看路径中匹配的所有命令。 - AlG
我相信这仅适用于命令($PATH上的可执行文件),而不是函数。 - Olivier Lacan
"which" 是有问题的,因为有多个实现,其中许多完全做错了事情,还有一些似乎工作正常,但有奇怪的意外。你应该优先考虑使用 type - tripleee
1
不适用于别名和Bash函数。至少在Ubuntu上是这样。最好使用 type -a lshw - Marinos An

22

PATH是一个环境变量,可以使用echo命令显示:

echo $PATH

这是一个由冒号字符':'分隔的路径列表。

which命令可以告诉你运行命令时哪个文件会被执行:

which lshw

有时你会获得一个符号链接的路径; 如果你想跟踪该链接指向实际可执行文件所在的位置,可以使用readlink并将其输出作为which的输入:

readlink -f $(which lshw)

-f参数指示readlink递归地跟随符号链接。

这是我的机器上的一个示例:

$ which firefox
/usr/bin/firefox

$ readlink -f $(which firefox)
/usr/lib/firefox-3.6.3/firefox.sh

1
对我来说,which ack 返回 ack: aliased to ...,因此无法在脚本中工作。 - Hi-Angel

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

一些解释可能对未来的读者有所帮助:要找到二进制文件,你需要使用 -b 选项,然后可以将其与 awk 结合使用以获取路径。因此,类似这样:whereis -b ack | awk '{print $2}' - Hi-Angel

3
在TENEX C Shell中,tcsh,可以使用where命令列出命令的位置或者是否为内置命令,例如:
tcsh% where python
/usr/local/bin/python
/usr/bin/python

tcsh% where cd
cd is a shell built-in
/usr/bin/cd

曾经有一段时间,tcsh 是很受欢迎的,但那是在开源 Bourne 兼容 shell 变得广泛可用之前。 - tripleee

3

一个替代 type -a 的方法是 command -V

由于大多数情况下我只对第一个结果感兴趣,所以我也会使用 head 命令。这样,在 bash 函数的情况下,屏幕不会被代码淹没。

command -V lshw | head -n1

你能更详细地解释一下 command -V 吗?我看到了 command -v 的使用,但不知道它们之间有什么不同。 - VimNing
1
-V 更加详细,它会打印出 lshw is /usr/bin/lshw,而 -v 只会打印 /usr/bin/lshw - Marinos An
我在哪里可以找到command本身的文档? - VimNing
@VimNing 你尝试过 command --help 吗? - Marinos An
是的,但我得到了“zsh:找不到命令:--help”的错误提示,我再试了一遍,结果还是一样。 - VimNing
@VimNing 然后你可以执行:man zshbuiltins。然后向下滚动一点,你就会找到 command 内置命令的文档。 - Marinos An

3

TLDR 答案

使用命令:whereis -b lshw

解释

使用whereis命令。从手册页面中可以得知:

whereis - 查找命令的二进制文件、源代码文件和手册页文件。

常用选项

此外,你还可以指定你要查找的内容:

  • whereis -b packagename: 查找二进制文件的位置。
  • whereis -m packagename: 查找手册的位置。
  • whereis -s packagename: 查找源代码的位置。

在你的情况下,由于你正在寻找二进制文件,所以你需要使用:whereis -b lshw

这个命令还有其他的选项,请参考手册页面。如果没有与包名称相关联的文件,则会显示空行。

示例

以下是一些真实世界中的用法:

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:

1
whereis 不是标准命令。最好使用 POSIX 规定的 typecommand - tripleee

1

Korn shell(ksh)提供了内置命令whence,可以识别其他shell内置命令、宏等。然而,which命令更具可移植性。


2
在ksh中,“whence -a”类似于Bash的“type -a”。 - Dennis Williamson

1
zsh 中(在我的情况下当前版本为5.9),你可以使用前缀=来检查某个命令所在的目录。 例如,如果你想知道mkdir命令所在的位置,你可以使用以下命令:
$> ls -l =mkdir
-rwxr-xr-x 1 root root 76216 Jun 14 20:49 /usr/bin/mkdir

或更简单地说:
$> echo =mkdir
/usr/bin/mkdir

注意:此方法仅适用于根据您的$PATH环境变量在当前 shell 中可用的命令。因此,如果您的$PATH的值为"/home/user/bin:/usr/bin:/usr/local/bin",则只有这三个路径下的命令将可用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接