Hacker News new | ask | show | jobs
by deathanatos 107 days ago
> I'd give this a try, works with any language:

  #!/usr/bin/env -S "/path/with spaces/my interpreter" --flag1 --flag2
This won't do what you're thinking it does. If I run that, I get:

  env: No terminating quote for string: /path/with"/path/with
… because the string you've given env -S on my system is malformed, and lacks a terminating quote. (You can test this w/ just giving an unterminated quoted string to env … I have no idea why the messaging is so funky looking, but that's sort of par for the course here.)

As I alluded to in my post, shebangs don't handle escaping. Now, yes, you're thinking that env will do it, here. The other problem with shebangs is that they're ridiculously unstandardized. On Linux, for example, that shebang will parse out to:

  #!/usr/bin/env -S "/path/with spaces/my interpreter" --flag1 --flag2

  argv[0]: "/usr/bin/env"
  argv[1]: "-S"
  argv[2]: "\"/path/with spaces/my interpreter\" --flag1 --flag2"
  argv[3]: <script filename>
& then -S proceeds as you expect it to. Things appear to work.

On my system,

  #!/usr/bin/env -S "/path/with spaces/my interpreter" --flag1 --flag2

  argv[0]: "/usr/bin/env"
  argv[1]: "-S"
  argv[2]: "\"/path/with"
  argv[3]: "spaces/my"
  argv[4]: "interpreter"
  argv[5]: "--flag1"
  argv[6]: "--flag2"
  argv[7]: <script filename>
This is because Linux passes everything after the first space as a single arg. macOS splits on spaces, but does no further processing (such as some form of backslash escapes) beyond that.

Since,

  env -S '"/path/with' <other args…>
is nonsense, env errors out with the above error.
1 comments

It works fine with GNU env with -S support, and a GNU-compatible kernel. I'm aware that won't work on some other systems, hence the 9 other examples. I said I would try that first and see how it goes, and low and behold it works fine on the systems I use.

  $ cat bbb.ml 
  #!/usr/bin/env -S "/home/user/.local/bin/o c a m l" -no-version
  print_endline "ok";;
  $ ls -lh ~/.local/bin/"o c a m l"
  lrwxrwxrwx 1 user user 14 Feb 27 07:26 '/home/user/.local/bin/o c a m l' -> /usr/bin/ocaml
  $ chmod a+rx bbb.ml
  $ ./bbb.ml
  ok
  $ 
But if it didn't work, you can get pretty good mileage out of abusing sh to get the job done for many popular languages.