Why does this sh shebang not work?
First, make the script executable:
chmod u+x script.sh
Second, your current directory is not in your $PATH. Therefore, you have to run the script with a path (relative is enough):
./script.sh
Bash script doesn't work without shebang BUT the shebang results in an error message
You have an encoding problem.
Look at: https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8
A text editor or web browser misinterpreting the text as ISO-8859-1 or CP1252 will display the characters  for this.
Save your file as UTF-8 without BOM or use system editor (vi, ...)
Should I use a Shebang with Bash scripts?
On UNIX-like systems, you should always start scripts with a shebang line. The system call execve
(which is responsible for starting programs) relies on an executable having either an executable header or a shebang line.
From FreeBSD's execve manual page:
The execve() system call transforms the calling process into a new
process. The new process is constructed from an ordinary file, whose
name is pointed to by path, called the new process file.
[...]
This file is
either an executable object file, or a file of data for an interpreter.
[...]
An interpreter file begins with a line of the form:
#! interpreter [arg]
When an interpreter file is execve'd, the system actually execve's the
specified interpreter. If the optional arg is specified, it becomes the
first argument to the interpreter, and the name of the originally
execve'd file becomes the second argument
Similarly from the Linux manual page:
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]
In fact, if a file doesn't have the right "magic number" in it's header, (like an ELF header or #!
), execve
will fail with the ENOEXEC error (again from FreeBSD's execve manpage):
[ENOEXEC] The new process file has the appropriate access
permission, but has an invalid magic number in its
header.
If the file has executable permissions, but no shebang line but does seem to be a text file, the behaviour depends on the shell that you're running in.
Most shells seem to start a new instance of themselves and feed it the file, see below.
Since there is no guarantee that the script was actually written for that shell, this can work or fail spectacularly.
From tcsh(1):
On systems which do not understand the `#!' script interpreter conven‐
tion the shell may be compiled to emulate it; see the version shell
variable. If so, the shell checks the first line of the file to see if
it is of the form `#!interpreter arg ...'. If it is, the shell starts
interpreter with the given args and feeds the file to it on standard
input.
From FreeBSD's sh(1):
If the program is not a normal executable file (i.e., if it
does not begin with the “magic number” whose ASCII representation is
“#!”, resulting in an ENOEXEC return value from execve(2)) but appears to
be a text file, the shell will run a new instance of sh to interpret it.
From bash(1):
If this execution fails because the file is not in executable format,
and the file is not a directory, it is assumed to be a shell script, a
file containing shell commands. A subshell is spawned to execute it.
You cannot always depend on the location of a non-standard program like bash. I've seen bash in /usr/bin
, /usr/local/bin
, /opt/fsf/bin
and /opt/gnu/bin
to name a few.
So it is generally a good idea to use env
;
#!/usr/bin/env bash
If you want your script to be portable, use sh
instead of bash
.
#!/bin/sh
While standards like POSIX do not guarantee the absolute paths of standard utilities, most UNIX-like systems seem to have sh
in /bin
and env
in /usr/bin
.
VS Code does not recognize shebang for bash
The "set the executable bit" trick works, but I'm not sure where that information is stored or if it's persisted across reboots. I just remembered a better solution: file associations!
Just add this to project/.vscode/vscode.json
(the key should be the name of the file):
{
"files.associations": {
"jobname-batch": "bash"
}
}
Shell script saying Command not found. Ignoring shebang?
The reason for this can be one of several things. To list the most common:
- The file does not have executable permissions. Use
chmod a+x foo.sh
to give all users execute permissions. - Your shebang is incorrect, double-check the path. Use
which sh
and copy the result after a#!
- Your lines are delimited with DOS feeds. Scripts need to be delimited with
\n
. Text editors such asnano
allow you to convert by choosingWrite-out
then pressingAlt+D
to toggle DOS format off. Utilities such asdos2unix
can convert files directly on the command line (although it may need installing first).
Shell script working fine without shebang line? Why?
shebang line is needed in the file and only if it's meant to be run as executable (as opposed to sh file.sh
invocation. It is not actually needed by script, it is for the system to know how to find interpreter.
EDIT: Sorry for misreading the question. If the shebang line is missing or not recognized, /bin/sh
is used. But I prefer being explicit about the interpreter.
Note, that this behavior is not universal, IIRC, only some exec*
family function do that (not to mention different platforms), so that's another reason to be explicit here.
Call a python script with a shebang
First, rename the file from foo.py
to foo
.
Then, move the file to /usr/local/bin/
or /home/user/.local/bin
if the script will only be executed by a single user. Instead, if your script is placed somewhere in the system for example "/path/to/foo", you could add your "/path/to/foo" to the $PATH variable.
After opening a new terminal session. You should be able to execute the script without the "./" and ".py".
By the way "./" means that you want to execute a file in the current working directory. It is always possible to execute a file using a full path of the file, for example "/usr/bin/something_to_run".
Please consider reading about PATH variable here.
Do you need shebang in all bash scripts?
The shebang is only mandatory for those scripts, which shall be executed by the operating system in the same way as binary executables. If you source in another script, then the shebang is ignored.
On the other hand. IF a script is supposed to be sourced, then it is convention to NOT put any shebang at the start.
Related Topics
How to Disable Hardware Prefetcher in Core I7
Install Binaries into /Bin, /Sbin, /Usr/Bin and /Usr/Sbin, Interactions with --Prefix and Destdir
Netcat Tcp Programming with Bash
Measuring Stack Usage for Linux Multi-Threaded App
Changing the Owner of an Existing Process in Linux
Is It Safe to Call Dlclose(Null)
How to Get the Output of Ansible Ad-Hoc Command in JSON, CSV or Other Format
How to Keep Program Running in Background in Ash Shell
Linking a Dynamically Linked Executable with Ld
What Is a Good Linux Exit Error Code Strategy
Focas Fwlib32 Cnc Library on Linux Platform
Native Linux App to Edit Win32 Pe Like Reshacker
Sort Entries of Lines Using Shell
Shell Script: Hexadecimal Loop
How to Use the Parallel Command to Exploit Multi-Core Parallelism on My MACbook
Delete Repeated Characters Without Back-Referencing with Sed