The shebang (#!
) is what's called a magic number. #!
is the readable form of the 2 bytes 0x23 and 0x21. If you see the man page for the C function execve()
the family of these exec functions what's picking up on these bytes and behaving differently when present.
excerpt from execve() man page
DESCRIPTION
execve() executes the program pointed to by filename. filename must be
either a binary executable, or a script starting with a line of the form:
#! interpreter [optional-arg]
For details of the latter case, see "Interpreter scripts" below.
argv is an array of argument strings passed to the new program. envp is
an array of strings, conventionally of the form key=value, which are
passed as environment to the new program. Both argv and envp must be
terminated by a null pointer. The argument vector and environment can be
accessed by the called program's main function, when it is defined as:
int main(int argc, char *argv[], char *envp[])
execve() does not return on success, and the text, data, bss, and stack
of the calling process are overwritten by that of the program loaded.
If the current program is being ptraced, a SIGTRAP is sent to it after a
successful execve().
The keen eye will notice that the form of the shebang takes only 2 arguments. One being the interpreter, the other an [optional-arg]
. This is why you can't pass more than 1 argument, at least on Linux.
So commands like this won't work, the -f
is ignored, I believe.
#!/usr/bin/foo -i -f
However, if the interpreter supports it, you can get around this limitation to a degree by doing it this way:
#!/usr/bin/foo -if