旁注2:使用的另一个好处./ 是避免与与本地可执行文件共享相同名称的系统实用程序混淆。尽管在这个特定问题中,它专门讨论了a.out可执行文件名称(在编译 C 代码时自动分配),但如果编译代码并将输出命名为可执行文件test(即gcc -o test test.c生成可执行文件并且您在 shell 中test调用testnot as command)会发生什么情况./test?
COMMAND EXECUTION
After a command has been split into words, if it results in a simple command
and an optional list of arguments, the following actions are taken.
If the command name contains no slashes, the shell attempts to locate it.
If there exists a shell function by that name, that function is invoked as
described above in FUNCTIONS. If the name does not match a function, the
shell searches for it in the list of shell builtins. If a match is found,
that builtin is invoked.
If the name is neither a shell function nor a builtin, and contains no
slashes, bash searches each element of the PATH for a directory containing
an executable file by that name.
这取决于您的 $PWD 是什么。
./a.out
告诉系统在当前目录中查找 a.out,因为您已经提供了文件的路径a.out
a.out
仅当 $PWD(您当前的工作目录)恰好位于 $PATH 或搜索二进制文件的目录中时才有效。只有在搜索字段中列出您的当前目录时才会搜索它,从而减少错误并通过避免错误潜在地提高安全性。
Shell 行为由 POSIX 标准化,并且出于安全原因无法识别当前工作目录中的可执行文件。单独并
a.out
不能讲述完整的故事。具体来说,这被定义为 Shell 命令语言的 POSIX 标准中的标准行为,在所有特定于 shell 的扩展和重定向以及内置查找完成后的命令搜索和执行部分:
至于
a.out
shell,只是一串文本。根据文本字符串的排列方式,shell 需要去除重定向、变量替换和扩展;之后剩下的就是一个“命令”,它可能是也可能不是内置的。a.out
不是内置在任何常见的外壳中,所以这就是./
发挥作用的地方。当然,你可以添加
.
到PATH
变量中,它会起作用——你就可以调用了a.out
。但这是一种非常糟糕的做法和安全风险:请参阅添加 . 到我的路径?怎么来的?.换句话说,不,它不是多余的。这就是 shell 应该如何工作的,并且由于技术原因而存在。
旁注1: 根据手册bash(1)
bash
也接受零长度字段:PATH
旁注2:使用的另一个好处
./
是避免与与本地可执行文件共享相同名称的系统实用程序混淆。尽管在这个特定问题中,它专门讨论了a.out
可执行文件名称(在编译 C 代码时自动分配),但如果编译代码并将输出命名为可执行文件test
(即gcc -o test test.c
生成可执行文件并且您在 shell 中test
调用test
not as command)会发生什么情况./test
?shell 会
/usr/bin/test
根据变量/usr/bin
中的列表找到PATH
并执行该特定的二进制文件,而不是test
当前工作目录中命名的可执行文件。事实上,我之前已经回答过一个关于这种情况的问题:运行 shell 脚本时,'test' 和 'test.sh' 有什么区别?来自
man bash
:换句话说,如果你在没有前导的情况下调用可执行文件
./
,shell 将在 PATH 中搜索命令并且找不到该命令,因为当前目录不在你的 PATH 中。如果将当前目录添加到 PATH,则可以调用不带前导./
.