列出外壳程序知道的所有命令


32

我可以在bash将列出所有可识别命令的外壳程序(恰好是)上键入什么?

另外,这在外壳方面是否有所不同?还是所有的shell都只有它们识别的命令的“目录”?

其次,另一个问题,但是我该如何覆盖那些问题呢?换句话说,我该如何编写自己的view命令来替换Ubuntu系统上现有的命令,该命令似乎只是在加载vim


5
请不要合并问题。将每个问题发布为一个单独的问题。
terdon

unix.stackexchange.com/q/63073/135943的副本几乎是重复的 (我已经双向链接了)。–
通配符

Answers:


61

您可以使用compgen

compgen -c # will list all the commands you could run.

仅供参考:

compgen -a # will list all the aliases you could run.
compgen -b # will list all the built-ins you could run.
compgen -k # will list all the keywords you could run.
compgen -A function # will list all the functions you could run.
compgen -A function -abck # will list all the above in one go.

4
请注意,compgen -c将包括诸如此类{while严格说来不是命令的东西。
斯特凡Chazelas

13

Shell知道四种命令。

  • 别名:这些是带有某些选项的命令的昵称。它们在外壳的初始化文件(~/.bashrc用于bash)中定义。
  • 功能:它们是给定名称的Shell代码段。与别名一样,它们在外壳的初始化文件中定义。
  • 内置函数:Shell附带了少量内置命令。大多数内置程序会操纵外壳状态(cd更改当前目录,set更改选项和位置参数,export更改环境等)。大多数外壳提供基本相同的内建函数,但每个外壳都对基本集合进行了一些扩展。
  • 外部命令:它们独立于外壳。与其他程序一样,shell通过在可执行搜索路径中查找外部程序来执行外部程序。该PATH环境变量包含搜索程序目录的冒号分隔的列表。

如果存在相同名称的几种类型的命令,则按上述顺序执行第一个匹配项¹。

您可以通过运行查看名称对应的命令类型type some_name

您可以通过alias不带参数运行内置函数来列出别名。没有办法列出所有外壳程序都适用的函数或内建函数。您可以在外壳程序的文档中找到内建列表。

在bash中,set内置列表列出了函数及其定义和变量。在bash,ksh或zsh中,typeset -f列出函数及其定义。在bash中,您可以使用列出任何类型的所有命令名称compgen -c。您可以使用compgen -A aliascompgen -A builtin compgen -A function特定类型的list命令。您可以传递一个附加字符串以compgen仅列出以该前缀开头的命令。

在zsh中,你可以列出一个给定类型的当前可用的命令echo ${(k)aliases}echo ${(k)functions}echo ${(k)builtins}echo ${(k)commands}(即最后一个仅列出外部命令)。

以下与shell无关的代码段列出了所有可用的外部程序:

case "$PATH" in
  (*[!:]:) PATH="$PATH:" ;;
esac

set -f; IFS=:
for dir in $PATH; do
  set +f
  [ -z "$dir" ] && dir="."
  for file in "$dir"/*; do
    if [ -x "$file" ] && ! [ -d "$file" ]; then
      printf '%s = %s\n' "${file##*/}" "$file"
    fi
  done
done

Bash有一个极端的情况:散列命令。

Bash参考手册说:

仅当在哈希表中找不到命令时,才对$ PATH中的目录进行完全搜索

尝试:

set -h
mkdir ~/dir-for-wat-command
echo 'echo WAT!' >~/dir-for-wat-command/wat
chmod +x ~/dir-for-wat-command/wat
hash -p ~/dir-for-wat-command/wat wat
wat

PATH环境变量不包含~/dir-for-wat-commandcompgen -c不显示wat,但可以运行wat

如果要隐藏现有命令,请定义别名或函数

¹ 例外:一些内建函数(称为特殊内建函数)不能被函数遮蔽-bash和zsh在默认情况下不符合POSIX。


另一种极端情况是,对于$PATHlike /bin:/usr/bin:(trailing :)的值,它将无法在当前目录中列出可执行文件。
斯特凡Chazelas

3

命令列表由两部分组成:

  1. 内置于shell的命令
  2. 您的命令 PATH

您无法更改内置插件,但是可以通过指定完整的路径名(例如)来防止外壳程序使用内置插件/bin/echo

至于中的命令PATH,您可以更改它。 PATH是一个用冒号分隔的目录列表,用于在其中查找命令。找到的第一个匹配文件为“ wins”。

export PATH=~/bin:${PATH}

(此语法不适用于csh衍生的shell,但不适用于我所知道的所有其他语法)。

导出时将PATH~/bin作为第一个条目,然后是其余的现有PATH条目。因此,现在您的外壳将检查directory calledbin in your home directory for a command *first* before checking the standardPATH`系统设置。您可以使用以下方法轻松地使其最后检查新目录:

export PATH=${PATH}:~/bin

PATH保留以后的登录名,请将其添加到.profile或其他Shell rc文件中。



1

如果按Tab键两次,然后按y,您将获得当前Shell中所有可用命令的列表。对于第二个问题,我认为您应该使用alias:shell alias


关于别名,当在系统上的任何位置(例如,从Shell脚本)调用命令时,这是一种覆盖和取消覆盖(通过“取消别名”)命令的简单方法吗?
themirror

1
您使用什么外壳?我无法使用双击选项卡列出bash上的所有命令。
terdon

我在Ubuntu 13.04上使用bash。还有一个名为compgen的命令,可用于获取bash上所有可用命令的列表。
coffeMug

@terdon您是否已安装bash完成功能?
coffeMug

1
设置所有模棱两可的选项
coffeMug
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.