/usr/bin/env: zsh -: 没有那个文件或目录

kjo*_*kjo 3 scripting zsh env shebang

我收到错误

/usr/bin/env: zsh -: No such file or directory
Run Code Online (Sandbox Code Playgroud)

...当我运行以zsh以下shebang行开头的可执行脚本时:

#!/usr/bin/env zsh -
Run Code Online (Sandbox Code Playgroud)

此外,FWIW,替换---原因/usr/bin/env打印关于zsh --.

我只在 ubuntu 下看到过​​这个错误,而且只在 shebang hack 的上下文中看到过。在达尔文下,相同的脚本运行良好。在 ubuntu 下,运行

% /usr/bin/env zsh -
Run Code Online (Sandbox Code Playgroud)

从命令行成功。(实际上,“在 ubuntu 下”应该理解为“在 ubuntu 12.04 LTS 和env (GNU coreutils) 8.13”下的简写。)

我的问题是:如何修改上面的shebang以避免此错误?

当然,我知道删除尾随-会消除错误,但这不是一个可以接受的解决方案。这篇文章的其余部分解释了原因。

导致错误的 shebang 行是为了遵守两个完全独立的准则:

  1. 要使脚本可移植,请使用#!/usr/bin/env <cmd ...>而不是#!/path/to/cmd <...>.

  2. -作为唯一参数zsh在zsh的脚本横座板某类的家当线的攻击

所以,我可以更准确地重申我的问题如下:是否有可能同时满足这两个准则而不会在 ubuntu 下触发上面显示的错误?

Ran*_*832 5

Linux(您提到“仅在 Ubuntu 下”,但您提到的唯一操作系统是 Darwin)不支持将多个参数传递给“shebang”解释器。它将整个字符串(在您的情况下,"zsh -")作为单个参数传递。

确保您的包不依赖于解释器位置的正确方法是,作为安装过程的一部分,定位解释器并修改脚本以包含正确的路径。http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sh.html#tag_20_117_16sh提供了一些用于执行此操作的示例代码(用于)。


Kei*_*son 5

我认为你的问题的答案基本上是“不”。Shebang 机制并不那么灵活。

#!行仅允许您指定要执行的命令以及(可选)该命令的单个参数。脚本的名称作为另一个参数传递。所以如果foo.zsh开始于:

#!/usr/bin/env zsh
Run Code Online (Sandbox Code Playgroud)

跑步foo.zsh就相当于跑步/usr/bin/env zsh foo.zsh

如果直接指定路径zsh,则可以传递附加参数:

#!/usr/bin/zsh -
Run Code Online (Sandbox Code Playgroud)

但有了#!/usr/bin/envhack,zsh 就有了额外的争论。

显然,正如您所见,这种行为因系统而异。顺便说一句,我会检查以确保-Ubuntu 上的 没有被忽略。

如果您可以依赖zsh在您关心的所有系统上处于一致的位置,则可以使用#!/usr/bin/zsh -(忽略您的第一个准则)。

如果不能,那么您可以zsh在每个系统上的一致位置创建符号链接,也可以#!在安装脚本时修改脚本中的行。(在 Perl 并不总是存在的日子里,我自己为 Perl 脚本做过这个/usr/bin/perl。)

或者,您可以编写一个包装器,当不带参数调用时,使用zsh参数调用-,并将 shebang 更改为:

#!/usr/bin/env zsh-wrapper
Run Code Online (Sandbox Code Playgroud)

它只需要zsh-wrapper位于 中的某个位置$PATH,不一定位于一致的位置。

另请参阅这个问题我的回答,以讨论#!/usr/bin/env黑客的优点和缺点。

请参阅此页面,了解有关各种类 Unix 系统上 shebang 行为的更多信息(感谢 Stephane Chazelas 提供的链接)。