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

Gan*_*rei 10 shell path shell-builtin

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

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

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

我在etc/bash.bashrc 中修改了我的路径,如下所示:

PATH=.:$PATH
Run Code Online (Sandbox Code Playgroud)

我已将此程序保存为 set.c 并正在编译它

gcc -o set set.c
Run Code Online (Sandbox Code Playgroud)

在文件夹中

~/Programming/so
Run Code Online (Sandbox Code Playgroud)

然而,当我打电话

set 2 3
Run Code Online (Sandbox Code Playgroud)

没发生什么事。没有出现的文字。

打电话

./set 2 3
Run Code Online (Sandbox Code Playgroud)

给出预期的结果

我以前从未遇到过 PATH 问题

which set
Run Code Online (Sandbox Code Playgroud)

返回./set。所以看起来 PATH 是正确的。这是怎么回事?

yel*_*hil 24

而不是使用which,这时候你最需要的时候不工作,使用type,以确定当你输入一个命令究竟会运行:

$ which set
./set
$ type set
set is a shell builtin
Run Code Online (Sandbox Code Playgroud)

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

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

$ function set { ./set; }
$ type set
set is a function
set ()
{
    ./set
}
Run Code Online (Sandbox Code Playgroud)

(在工作bash,但其他像炮弹ksh可能不答应。见mikeserv的一个更便携的解决方案的回答。)

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

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

  • @GaneaDanAndrei 主要是使用`type`代替`which`,不要将你的程序命名为“set”,并实现`function set { ./set; }` 是一个你应该避免的丑陋黑客。 (4认同)
  • 你推荐 `type` 而不是 `which`,但不要给出任何理由。([我知道为什么](http://unix.stackexchange.com/a/10529/2421),但需要推荐的人不会。) (3认同)

kli*_*ist 11

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

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

  • 使用`./foo` 来调用一个*是*专业的程序;它表明你明白为什么`.` 不应该在$PATH 中。你的老师错了,你可以告诉他我是这么说的。 (15认同)
  • `cd` 是一个内置的 shell,所以这个例子不会像 `set` 那样工作。 (4认同)
  • 是的,这是一个愚蠢的想法,我的老师强迫我们在演示程序时不要看起来不专业”。如果没有完成,他会给你打分。 (2认同)

mik*_*erv 10

set是不是只是一个内置的,它是一个POSIX特殊内建。有哪些是标准的规定在其他任何命令之前搜索中发现了几个内置命令-$PATH不搜索,功能名称不搜索,等其最建宏不是 特别实际需要POSIX标准是在你发现$PATH 之前, shell将运行任何自己的内置程序。这是真实的echo,其余的大多数(但是否在这方面很荣幸的标准在过去在开放群组邮件列表一直是争论的问题),但不是settrapbreakreturncontinue.:timesevalexitexportreadonlyunset、 或exec

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

但是,如果您确实希望入侵它,则可以使用alias. shell扩展的顺序支持这种变通方法。因为在alias读取命令set时扩展了,所以在定义中替换名称的任何内容都会正确扩展,它可能不应该扩展为这些名称之一。

所以你可以这样做:

alias set=./set
Run Code Online (Sandbox Code Playgroud)

...这将工作得很好。