4 ms·
This problem has been solved on at least Linux (GNU coreutils ≥ 8.30, 2018-07-01), FreeBSD (≥ 6.0, 2005-11-04), and macOS with the env -S option: #!/usr/bi
by anderskaseorg 4y ago
This problem has been solved on at least Linux (GNU coreutils ≥ 8.30, 2018-07-01), FreeBSD (≥ 6.0, 2005-11-04), and macOS with the env -S option:
#!/usr/bin/env -S interpreter --arg --arg
https://www.gnu.org/software/coreutils/manual/html_node/env-invocation.html#g_t_002dS_002f_002d_002dsplit_002dstring-syntax https://www.gnu.org/software/coreutils/manual/html_node/env-...
https://www.freebsd.org/cgi/man.cgi?env https://www.freebsd.org/cgi/man.cgi?env
https://www.unix.com/man-page/mojave/1/env/ https://www.unix.com/man-page/mojave/1/env/
- kazinator 4y agoI know about this, and in fact I wrote an alternative solution for GNU Coreutils env in 2017: a complete patch with updated documentation and test cases. Here is a problem: interpreters take arguments such as options ... but, separately, so do interpreted programs. Sometimes, you'd like to control both. I made an extension to env whereby you could do: #!/usr/bin/env :interp:--foo:{}:--bar This would find the "interp" interpreter using a PATH search and then pass it the arguments --foo <scriptname> --bar, followed by arguments that came from the invocation of the hash-bang script. If the special argument {} does not appear, then interp will be invoked with --foo --bar <scriptname>: the script name is not relocated into the arguments. However, the maintainer expressed a preference for compatibility with FreeBSD -S. I took a look at the requirements and saw that FreeBSD's env -S was doing a whole lot of stuff: interpreting C-like character escape sequences like \n, and interpolating dollar-sign-sigiled variables like $USER. In spite of all that, didn't see the feature of being able to insert the script name into the middle of the arguments, like in my solution. It amounted to throwing away my patch and implementing some FreeBSD stuff I had no interest in and a lot of which I thought was a bad idea, while failing to achieve my original functionality. So, I just did the first part: throwing away my patch.
- anderskaseorg 4y agoThe typical use case for env -S is a script passing arguments to the interpreter (#!/usr/bin/env -S interp --foo → interp --foo ./scriptname), and the user can always pass arguments to the script (./scriptname --bar → interp --foo ./scriptname --bar). But why would a script ever need to use a shebang to pass an argument like --bar to itself? Can’t it just modify its own argv, or act as if it had? (I found your message at https://lists.gnu.org/archive/html/coreutils/2017-05/msg00021.html https://lists.gnu.org/archive/html/coreutils/2017-05/msg0002... that claims > It is useful because it allows the hash bang to specify some arguments after the script (which could be arguments belonging to the script rather than to the interpreter, for instance). but doesn’t really explain why the script itself would want to specify that.) In any case, compatibility is important here, in order for it to be possible to write cross-platform scripts.
- kazinator 4y agoHere is a use case not involving the motivation to pass canned options passed to the script. Suppose that the interpreter is such that the script name must be passed as an option. For instance, Awk implementations are like this: awk -f <script> The problem is that this kind of option is allowed to be followed by more options. awk -f <script> -Z # error under GNU awk: -Z is an invalid option See where this is headed? If we have #!/usr/bin/awk -f awk script here and we call this as $ ./script -Z it will pass that option to Awk. But the script wanted to handle that option! $ ./script -- -Z # process -Z as argument to the script and wouldn't it be nice if we could hide this "--" argument in the hash bang? With my proposal you could do that: #!/usr/bin/env :awk:-f:{}:-- Now speaking of Awk, GNU awk has solved this particular problem itself. It has the option -E/--exec which works like -f, but is the last option to be processed. (Any of these kinds of issues can be solved locally for a given interpreter, if you control its implementation.)