为什么我的名为“set”的程序没有被执行?

为什么我的名为“set”的程序没有被执行?

我创建了一个简单的 C 程序,如下所示:

int main(int argc, char *argv[]) {

    if (argc != 5) {
       fputs("Not enough arguments!\n", stderr);
       exit(EXIT_FAILURE);
    }

我已经修改了我的路径等/bash.bashrc像这样:

PATH=.:$PATH

我已将此程序保存为 set.c 并使用以下命令编译它

gcc -o set set.c

在文件夹中

~/Programming/so

然而,当我打电话时

set 2 3

什么都没发生。没有出现任何文字。

呼唤

./set 2 3

给出了预期的结果

我以前从未遇到过 PATH 问题

which set

返回./set。所以看来 PATH 是正确的。发生什么事了?

答案1

而不是使用which, 其中当你最需要的时候却不起作用,用于type确定键入命令时将运行的内容:

$ which set
./set
$ type set
set is a shell builtin

shell 总是在搜索 之前查找内置函数$PATH,因此设置$PATH在这里没有帮助。

最好将可执行文件重命名为其他名称,但如果您的作业需要命名该程序set,则可以使用 shell 函数:

$ function set { ./set; }
$ type set
set is a function
set ()
{
    ./set
}

(这在 中有效bash,但其他 shellksh可能不允许这样做。请参阅 mikeserv 的答案以获得更便携的解决方案。)

现在输入set将运行名为“set”的函数,该函数执行./set. GNUbash在查找内置函数之前先查找函数,并且在搜索$PATH. bash 手册页中名为“COMMAND EXECUTION”的部分提供了更多相关信息。

builtin另请参阅和command:help builtin和的文档help command

答案2

set是 bash(可能还有大多数其他 shell)中的内置函数。这意味着 bash 在查找函数时甚至不会搜索路径。

顺便说一句,.出于安全原因,我强烈建议不要添加到路径中。想象一下,例如在任何其他用户添加可执行文件后cd退出。/tmp/tmp/cd

答案3

set不是只是一个内置的,它是一个POSIX 特殊内置。有一些内置命令是标准指定的,在命令搜索中首先找到它们 -$PATH不搜索,不搜索函数名称,等等。大多数内置命令是不是 特别的实际上是必需的按照 POSIX 标准,可以在您的$PATH shell 将运行它自己的任何内置过程。这对于echo大多数人来说都是如此(尽管过去在这方面是否遵守该标准一直是开放组邮件列表中争论的问题), 但不是set、、、、、、、、、、、、、、、、、或。trap​​​​​​​​​​​breakreturncontinue.:timesevalexitexportreadonlyunsetexec

所有这些都是 shell 的保留名称,除了命令搜索的优先顺序之外,它们还具有特殊属性。例如,您不能在符合标准的 shell 中使用任何这些名称定义 shell 函数。这是一个好东西- 它使人们能够编写可移植的脚本安全地。这些是基线命令,经验丰富的编剧可以根据这些命令在他或她的环境中建立安全可靠的立足点。入侵这个命名空间是不是建议。

但是,如果您确实希望入侵它,则可以使用alias.外壳顺序扩张启用此解决方法。由于 是alias在读取命令时展开的,因此无论您set在定义中用什么替换名称,都将正确展开,但它可能不应该扩展到这些名称之一。

所以你可以这样做:

alias set=./set

...这会工作得很好。

答案4

问题是这set是一个内置的 shell,最好的解决方案是使用不同的名称为您的可执行程序。

顺便说一句,上周我问了一个关于如何运行系统命令而不是同名的 shell 内置命令我接受的解决方案是通过以下方式运行命令env

env set 2 3

对于这种特殊情况,您已经知道要使用的命令位于当前目录中,最好通过输入其路径(用于.表示当前工作目录)来直接运行可执行文件:

./set 2 3

上述两种解决方案都与 shell 无关,即无论您使用哪种 shell,它们都可以工作。

诸如使用command内置命令之类的建议在 Bash 中不起作用:这只会阻止 shell功能从被运行。虽然没有记录,但我也注意到使用command也会抑制 shell关键词。但是,它不会对 shell 执行相同的操作内置函数例如set。据我了解,command可能与其他 shell(例如 zsh)一起使用。

另外,诸如\set"set"之类的技巧'set'对 Bash 内置函数不起作用——尽管它们对于运行可执行文件而不是有用别名或外壳关键词

注意:这个答案最初是作为对埃里克(已接受)答案的评论开始的,但变得太大而无法容纳评论。建议使用type而不添加.到 PATH 的其他答案都是很好的答案。

相关内容