0

From bash manual about shebang

Most versions of Unix make this a part of the operating system’s command execution mechanism. If the first line of a script begins with the two characters‘ #!’, the remainder of the line specifies an interpreter for the program. Thus, you can specify Bash, awk, Perl, or some other interpreter and write the rest of the script file in that language.

The arguments to the interpreter consist of a single optional argument following the interpreter name on the first line of the script file, followed by the name of the script file, followed by the rest of the arguments. Bash will perform this action on operating systems that do not handle it themselves. Note that some older versions of Unix limit the interpreter name and argument to a maximum of 32 characters.

Does "a optional argument" mean an argument to an option, or an argument which may be there or might not be?

Why "a single optional argument"? does it not allow multiple "optional arguments"?

If a script looks like

#! /path/to/interpreter --opt1 opt1-arg --opt2 opt2-arg --opt3 nonopt-arg1 nonopt-arg2

...

when I run the script in bash as

$ myscript arg1 arg2 arg3

what is the actual command being executed in bash? Is it

$ /path/to/interpreter --opt1 opt1-arg --opt2 opt2-arg --opt3 nonopt-arg1 nonopt-arg2 myscript arg1 arg2 arg3

Thanks.

Tim
  • 101,790

2 Answers2

6

The arguments to the interpreter in this case are the arguments constructed after interpretation of the shebang line, combining the shebang line with the script name and its command-line arguments.

Thus, an AWK script starting with

#! /usr/bin/awk -f

named myscript and called as

./myscript file1 file2

results in the actual arguments

/usr/bin/awk -f ./myscript file1 file2

The single optional argument is -f in this case. Not all interpreters need one (see /bin/sh for example), and many systems only allow at most one (so your shebang line won’t work as you expect it to). The argument can contain spaces though; the whole content of the shebang line after the interpreter is passed as a single argument.

To experiment with shebang lines, you can use #! /bin/echo (although that doesn’t help distinguish arguments when there are spaces involved).

See How programs get run for a more detailed explanation of how shebang lines are processed (on Linux).

Stephen Kitt
  • 434,908
  • Thanks. (1) "the whole content of the shebang line after the interpreter is passed as a single argument." do you mean "the whole content of the shebang line after the interpreter is passed as a single optional argument"? So even if it is not meant for being an optional argument, it is still interpreted as one? (2) If a shebang starts with #! /usr/bin/env interpreter, can there be more afterwards? not even an option? – Tim Aug 20 '17 at 17:56
  • (1) “Optional” isn’t an attribute carried by the argument; it’s the definition of the argument that’s optional. You can have a shebang line with an argument, or you can have a shebang line without one; that’s what makes it optional. (2) There can be more afterwards, but interpreter plus whatever comes after that will be passed to env as a single argument; try it with #!/usr/bin/env echo Testenv ends up trying to run a command called echo Test (all together) and failing. – Stephen Kitt Aug 20 '17 at 20:33
5

Read your execve(2) man page. The limitation on a single optional argument is OS dependent. Linux treats all words after the interpreter as one single argument

If you want to do this:

#! /path/to/interpreter --opt1 opt1-arg --opt2 opt2-arg --opt3 nonopt-arg1 nonopt-arg2

You should in fact do this

#!/bin/sh
exec /path/to/interpreter --opt1 opt1-arg --opt2 opt2-arg --opt3 nonopt-arg1 nonopt-arg2 "$@"
# ...................................................................................... ^^^^

UPDATE: I notice the env program has a -S option for just this purpose: the shebang can be (although if I had to maintain this program, I would not be happy)

#!/usr/bin/env -S /path/to/interpreter --opt1 opt1-arg --opt2 opt2-arg --opt3 nonopt-arg1 nonopt-arg2

Read your env(1) man page.

glenn jackman
  • 85,964