`command`是什么bash命令?

命令command没有手册条目,但帮助显示如下:
$ help command
command: command [-pVv] command [arg ...]
    Execute a simple command or display information about commands.
    
    Runs COMMAND with ARGS suppressing  shell function lookup, or display
    information about the specified COMMANDs.  Can be used to invoke commands
    on disk when a function with the same name exists.
    
    Options:
      -p    use a default value for PATH that is guaranteed to find all of
        the standard utilities
      -v    print a description of COMMAND similar to the `type' builtin
      -V    print a more verbose description of each COMMAND
    
    Exit Status:
    Returns exit status of COMMAND, or failure if COMMAND is not found.

问题

  • command -v 可以作为 which 的替代吗?
  • command 的目的和用法是什么?
6个回答

command 是一个 bash 内建命令,我们可以看到:

seth@host:~$ type command
command is a shell builtin

所以我们知道command是由我们的shell,bash提供的。深入研究man bash,我们可以看到它的用途是什么:
(来自man bash):
command [-pVv] command [arg ...]
              Run  command  with  args  suppressing  the normal shell function
              lookup. Only builtin commands or commands found in the PATH  are
              executed.   If the -p option is given, the search for command is
              performed using a default value for PATH that is  guaranteed  to
              find  all  of  the  standard  utilities.  If either the -V or -v
              option is supplied, a description of command is printed.  The -v
              option  causes a single word indicating the command or file name
              used to invoke command to be displayed; the -V option produces a
              more  verbose  description.  If the -V or -v option is supplied,
              the exit status is 0 if command was found, and  1  if  not.   If
              neither  option  is  supplied  and  an error occurred or command
              cannot be found, the exit status is 127.   Otherwise,  the  exit
              status of the command builtin is the exit status of command.  

基本上,你可以使用command来绕过“正常的函数查找”。例如,假设你在你的.bashrc文件中有一个函数:
function say_hello() {
   echo 'Hello!'
}

通常情况下,当你在终端运行say_hello时,bash会先在你的.bashrc中找到名为say_hello的函数,然后再找到一个名为say_hello的应用程序。使用:
command say_hello  

使bash绕过其正常的函数查找,直接进入内置函数或您的$PATH。请注意,此函数查找还包括别名。使用command将同时绕过函数和别名。

如果提供了-p选项,bash将绕过您自定义的$PATH并使用其自己的默认值。

-v-V标志会打印出命令的描述(对于-v是简短描述,对于-V是详细描述)。

注意:正如souravc在评论中指出的,可以在这里找到有关shell内置函数的信息的更简单方法:如何使`man`适用于shell内置命令和关键字?


1请查看这个链接 - sourav c.
3尝试运行sudo apt-get install manpages-posix命令来安装manpages-posix。默认情况下未安装。点击这里查看详细信息。 - sourav c.
我对Linux还很陌生,所以我还在学习命令。我了解了"command"命令的概念(只是有点害怕,因为我担心它可能会对我的系统造成一些损害)。只是想知道,学习"shell"这个东西重要吗? - Nori-chan
1@Nori-chan Bash 是Ubuntu的默认shell。它是解释你输入的命令并根据你输入的信息决定如何执行和处理的工具。通过学习Un*x命令行,你也在某种程度上学习了bash :) - Seth
只是想知道,因为我刚刚使用了“命令”,所以实际上,什么都没有发生对吧?另外,@Seth,感谢你编辑我的帖子(使其更准确)并回答我的问题。 - Nori-chan
@Nori-chan 是的,因为你没有输入任何参数运行 command,它只是静默退出了,实际上什么都没发生。谢谢提出这个很棒的问题! - Seth
你可以使用help command来获取内置命令的用法信息,而不必在man页面中搜索。 - LawrenceC
+1 对于一个很好的教学方式来回答。然而,我建议说command something会绕过名为something的函数和别名,而\something只会绕过别名something但会执行函数。据我所知,没有办法只绕过函数而不绕过同名的别名。(你的回答说"它绕过了函数(...)直接进入内置或者你的路径",但没有明确提到它也绕过了别名,这可能仍然需要被写得明确一些以便理解) - Olivier Dulac
@OlivierDulac 好观点,我没有考虑到那一点。手册上并没有明确说明,但经过测试,你是正确的。我会更新答案。 - Seth
vim /usr/bin/command 给出了 builtin echo ${0##*/} | tr \[:upper:] \[:lower:]` ${1+"$@"}。对于 vim /usr/bin/alias 也是一样的。我想知道这是什么意思? - Ben Butterworth
关键要点:「使用 command 命令将绕过函数和别名。」 - Gabriel Staples

这是Bash shell的内置命令。
我唯一看到的优点总结在以下帮助文本的句子中:

当存在同名函数时,可以用于在磁盘上调用命令。

所以,如果你想执行一个程序(保存在磁盘上的二进制文件),并且存在同名的内部shell函数,那么你可以使用这个内置命令来调用你的程序。
是的,command -v会给出与type相同类型的结果。
我还在Dash shell中找到了它。

2值得更明确地补充的是,尽管 command (name) 忽略了 shell 函数,但 command -v (name) 并不会。command -v (name) >/dev/null 应该是一种可移植的方式来检查具有该名称的命令是否存在,无论它是一个 shell 内建函数、函数还是外部工具。 - hvd
1command -v 是 POSIX 系统中的替代 which、type 等命令的选项。 http://stackoverflow.com/questions/762631/find-out-if-a-command-exists-on-posix-system - Javier López
作为一个真实世界的例子,Android AOSP构建环境(在v4.2.2之后的某个时候)定义了一个名为'make'的shell函数,它会输出有关构建是否成功以及所花费时间的信息。AOSP构建环境中的其他shell函数使用command make来调用实际的make程序。不幸的是,当AOSP环境开始向make程序输出添加一些东西时,我的其他shell脚本就出问题了,而且非常恼人,因为我很难弄清楚那些额外的输出是从哪里冒出来的。 - Michael Burr

它有两种不同的用途:
一种用途是忽略别名和函数,并在PATH中找到可执行文件时运行它,即使存在同名的别名或函数。
例如,我将使用一个别名来为ls命令添加一个/符号来表示目录名:
$ alias ls='ls --classify'
$ ls -d .
./
$ command ls -d .
.

在交互式 shell 中,使用反斜杠作为替代的更短语法可能更方便:
$ \ls -d .
.

另一个用途是使用选项-v来查找在不使用命令名称时将运行的命令。它似乎是最便携/POSIX变体的which
$ command -v ls
alias ls='ls --classify'
$ command -v sed
/bin/sed

绝对是我在这里的最喜欢的解释。它可以防止一个糟糕的命令,甚至更糟的是,如果一个别名已经有了分配的选项。例如,通过\execmd绕过execmd的别名。看到服务器的.bashrc文件中别名部分使用的命令后来才到这里 - 在那里你肯定不想要坏别名。有点有趣的难题,命令(command)被用于绕过别名。 - Cymatical
回复:“_它似乎是最便携/POSIX的变体之一。”- 对于我来说(以及在2022年),虽然command的行为如描述的那样,但which不知道别名。 - stafusa

command很有用,例如,如果您想检查特定命令的存在。which将别名包含在查找中,所以对于这个目的来说不合适,因为您不希望随机别名被视为所讨论的命令。

换句话说,您可以在shell脚本中有一个类似这样的小函数:

exists() {
  command -v "$1" >/dev/null 2>&1
}

然后测试是否有可用的命令(这里是dialog),像这样:
if ! exists dialog ; then
   echo "This script requires 'dialog'."
   echo "Install it with 'sudo apt-get install dialog', then try again!"
   exit 1
fi



我不完全确定是否建议将参数传递给命令时,不将&字符解释为主命令的另一个参数。 - jxramos
2这里不需要使用command,除非你也有一个名为ping的函数。在那里使用command对于解析&没有任何区别。 - muru