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
sh... or POSIX conformant C library functions like
popen()... in a POSIX environment, the file will be interpreted by a POSIX conformant
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
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/xpg6/bin and a historical (non-standard) one in
/bin. The default
/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
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
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.