I don't know what this guy is smoking, but this has never been a problem.
I don't know what this guy is smoking, but this has never been a problem.
I still write env bash shebangs to this day, in his honor. Happy to hear there's progress towards ending this archaic separation.
POSIX explicitly says "Applications should note that the standard PATH to the shell cannot be assumed to be either /bin/sh or /usr/bin/sh, and should be determined by interrogation of the PATH returned by getconf PATH [...]"
Worse: it’s in /usr/local/bin now (as ports are installed in /usr/local, by archaic convention).
To assume otherwise would have to assume that all ports come from FreeBSD and that's a bit absurd. I don't think anyone's going to say that Bash, or say KDE, is a "FreeBSD project" any time soon.
And all that just to point out that /usr/local on FreeBSD is intended for non-OS software installs (it's not the only option you have on the system, /opt isn't unheard of, but mixing up /usr/bin with non-OS software is a fast recipe for disaster).
It does make sense for your pythons and rubies but not really for bash.
Side note: zsh allows for #!bash but that's only interpreter I found that does that
Fix that one, and you can use
#!/usr/bin/env interpreter --arg --arg ...
Problem solved; no need to mess with the file system divisions.For that matter ... the stupid hash bang mechanism itself should do PATH resolution, maybe, you know?
#!/usr/bin/awk -f <-- find awk at that absolute path
#!awk -f <-- Just use the darn PATH, dear hash-bang handling code in the kernelNot to mention library linking and looking for various other data files.
I've run into this particular issue with stripped down containers.
I run a script as part of the container's CMD/ENTRYPOINT, and it fails.
Run it through an interactive shell, and hey-presto PATH is setup and script runs fine.
Perhaps if you started your entrypoint with “/bin/bash cmd”??
#!/usr/bin/env -S interpreter --arg --arg
https://www.gnu.org/software/coreutils/manual/html_node/env-...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.
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/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.
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.)
I wrote [0] in lua a while back (mind the comments), didn't destroy anything I think, I wrote [1] just now in gawk, so not as recommended.
FWIW the correct solution, is the plan9 one, just union mount/bind all paths to /bin.
-> ᛯ cat /tmp/1.sh
#!echo ble bla bla bla -n -e
-> ᛯ /tmp/1.sh
ble bla bla bla -n -e /tmp/1.sh
It's the best solution but it will take decades for that to migrate to other shellsThe exec fails when a shell tries to run an executable file that has no hash bang header, but also in a case like this when the header doesn't give a path that resolves to an interpreter.
Without the #!echo, I'm guessing Zsh would have interpreted the file as as Zsh script.
It's really not a huge issue for me, but it is at least a minor frustration. (And for people who maintain scripts across different distros / *nixes, I'm sure that it is a larger frustration).