3

I'm trying to figure out exactly what the semantics of the shebang are.

I can write a script like this:

#!/usr/bin/env bash

if [ -z "$FOO" ] then echo "No FOO" else echo "$FOO" fi

without $FOO in my environment, and run it like ./foo.sh, bash foo.sh, env bash foo.sh, etc and it will print "No FOO" as expected.

I can of course run it like FOO=bar ./foo.sh and it will print bar.

The env man page gives the invocation as:

env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]

And I can use it as such:

$ env FOO=bar bash foo.sh
bar

However, if I try to use that syntax in a shebang:

#!/usr/bin/env FOO=bar bash

if [ -z "$FOO" ] then echo "No FOO" else echo "$FOO" fi

then ./foo.sh hangs indefinitely and does not execute.

Can someone explain this to me? I assumed that when a shebang is encountered, it just copies the command, appends the path to the script to the end of the argument list, and executes it, but this behavior suggests otherwise.

1 Answers1

6

Most systems accept only up to one argument after the path of the interpreter in the shebang line. If you provide more than one, the behaviour depends on the system.

On Linux, all of what's after the interpreter (without leading and trailing space or tab characters) is passed as a single argument. So with a she-bang of:

#! /usr/bin/env FOO=bar bash

The system will call /usr/bin/env with FOO=bar bash and /path/to/the/script as arguments. Then env will run the script again with FOO=bar bash in its environment, and not bash with /path/to/the/script as argument (and FOO=bar in the environment), causing an infinite loop.

Some implementations of env, including FreeBSD's and recent versions of GNU env, can be told to do the splitting themselves with -S to work around that limitation.

In

#! /usr/bin/env -S FOO=bar bash

A "-S FOO=bar bash" single argument will still be passed to env, but env will split the " FOO=bar bash" argument of that -S option and will behave as if called with FOO=bar and bash as separate arguments.

See the GNU env manual or FreeBSD env manual for details as to how the splitting is done.