Zsh 如何区分实用程序/文件是否可执行二进制或脚本,或者只是文件,或 shell 内置等?
答案1
当一个单词出现在命令位置时,zsh 首先检查它是否是一个别名或一个保留字。作为语法分析的一部分,这种情况发生在早期。 Zsh 了解保留字和别名,因为它每个都有一个内部表。此外,如果后缀的形式是.ext
存在用 定义的活动后缀别名alias -s ext=…
,则以某些后缀结尾的单词将以类似于普通别名的方式扩展。保留字在 zsh 的源代码中是固定的(除了可以禁用)。别名可以在运行时定义。
当 zsh 准备好时执行命令,对于命令位置的单词:
- 如果该词出现在内表中功能,它作为函数执行。函数可以在运行时定义。
- 否则,如果该词出现在内表中内置函数。 zsh 的源代码中有一组初始内置函数,但可以通过以下方式定义其他内置函数动态加载的模块。
- 否则,如果
auto_cd
选项设置后,该单词是目录的路径,并且该命令没有参数,zsh 的行为就像该命令将该cd
单词作为参数一样。 - 否则,zsh 将该单词视为外部命令的名称。它执行一个
PATH
抬头就像系统功能一样execvp
,尽管像大多数 shell 一样 zshexecve
直接调用。 - 如果尝试执行外部命令失败但存在匹配的文件,zsh 可能会尝试间接执行该命令,具体取决于文件的内容:
- 如果文件以 开头
#!
,zsh 会读取该行上的解释器路径并尝试调用解释器。这是舍邦机制。在现代系统上,内核会处理这个问题,因此只有在某些古老的系统上才需要实现 zsh。 - 否则,如果该文件看起来像文本文件,则 zsh 会调用
/bin/sh
它。此行为是为了向后兼容 shebang 机制存在之前的情况,人们习惯于将 shell 脚本放入命令搜索路径中,然后由sh
.
- 如果文件以 开头
- 如果这些都无法执行命令,则 zsh 运行该函数
command_not_found_handler
,如果存在的话。此函数通常用于打印诸如“未找到命令'foo',但可以使用以下命令安装:sudo apt install somepackage”之类的消息,但它也可以尝试以某种不同的方式执行该命令。