If the first line of a file starts with #!
, the system treats it as a script whose interpreter follows #!
(and most interpreters ignore that line as #
is the comment leader in most of them). However the syntax of that shebang line and how it is interpreted varies from system to system and is unspecified by POSIX (though in the case of #! /bin/bash
alone, there's no ambiguity).
If you omit the shebang line on a text file, when executed by a POSIX conformant utility like env
, xargs
, find
's -exec
, awk
's system()
, vi
, sh
... or POSIX conformant C library functions like execl()
, execp()
, system()
, popen()
... in a POSIX environment, the file will be interpreted by a POSIX conformant sh
.
That's what POSIX specifies and same goes for Unix instead of POSIX.
Now, that leaves some uncertainty for what happens when the conditions described above are not meant.
For instance on all systems, the execve()
system call will fail to execute those scripts without a shebang. It's not the kernel that implements that logic of starting a POSIX sh
in that case, it's userspace applications/functions upon execve
actually returning ENOEXEC
upon attempted execution of the file.
What that means is that if an application (typically not one specified by POSIX) doesn't rely on POSIX execl()
, system()
... to execute a command but call execve()
directly, they will fail to execute those scripts. Rare but happens.
Now there's the question of the POSIX environment and what shell non-POSIX applications will call.
POSIX allows systems not to conform based on the environment, they even allow the POSIX environment not to be the default.
For instance, Solaris before Solaris 11, had several implementations of sh
(and other standard utilities), one standard in /usr/xpg4/bin
or /usr/xpg6/bin
and a historical (non-standard) one in /bin
. The default $PATH
had /bin
before /usr/xpg4/bin
. Also, what shell things like system()
called depended on how the application using them was compiled (with the default being the non-POSIX /bin/sh
shell). Even POSIX utilities there (like IIRC /usr/xpg4/bin/awk
) failed to start the proper shell in some circumstances (like in print | "some command"
in awk
IIRC).
What that meant is that on Solaris, when omiting the shebang, you could never be sure whether the script was going to be interpreted by a standard sh
or by the old Bourne shell in /bin
.
So, for portability, even if POSIX implies that you should not use a shebang if you want your script interpreted by a POSIX sh
, in practice, you generally have to and need to adapt the path depending on the system (like #! /usr/xpg4/bin/sh -
on Solaris and #! /bin/sh -
on most other systems).
Now, if you want your script to be interpreted by bash
(for instance because it uses bash
extensions over the standard sh
syntax), then there's no question, we're out of what POSIX specifies anyway, and you need to use a shebang there with the correct path to the bash
interpreter on the system that script is to be run.
./script.sh
and notbash script.sh
as in the latter case the#!
is just a comment. – tobyodavies Jul 24 '13 at 05:59