652

I have made Bash scripts before and they all ran fine without #!/bin/bash at the beginning.

What's the point of putting it in? Would things be any different?

Also, how do you pronounce #? I know that ! is pronounced as "bang."

How is #! pronounced?

pkamb
  • 33,281
  • 23
  • 160
  • 191
node ninja
  • 31,796
  • 59
  • 166
  • 254
  • 16
    You don't need to and you shouldn't unless you have no choice. Use '#!/bin/sh' while you can and learn about the difference between a (POSIX) shell and bash. There will come a day before your resume grows too much longer when you will find yourself on a system with a different shell and you still want your scripts to work. – Jens May 26 '12 at 16:21
  • 79
    It's pronounced "Hash-Bang" or "She-Bang". – Beachhouse Jan 09 '13 at 16:32
  • 32
    I think it's worth noting that this is only executed if you run your script as an executable. So if you set the executable flag and then type `./yourscript.extension`, for example, `./helloworld.py` or `./helloworld.sh`, it will look for the interpreter at that top line, which would be `#!/bin/python` or `!#/bin/bash`, whereas when executing the script like `python helloworld.py`, the first line will not be observed because it is commented out. So it is a special sequence for the shell/kernel. – jfa Jun 19 '15 at 16:33
  • @JFA is there a change in sequence between bash and python , when using !# for python and #! for bash ? – AAI Aug 30 '17 at 17:38
  • 2
    @AjeyaAnand no it was a mistype, good catch – jfa Aug 30 '17 at 17:56
  • Further reading: https://medium.com/@codingmaths/bin-bash-what-exactly-is-this-95fc8db817bf – carloswm85 Jul 17 '20 at 15:56
  • ... because it's many more there than just a bash – Sławomir Lenart Apr 06 '23 at 20:40

10 Answers10

534

It's a convention so the *nix shell knows what kind of interpreter to run.

For example, older flavors of ATT defaulted to sh (the Bourne shell), while older versions of BSD defaulted to csh (the C shell).

Even today (where most systems run bash, the "Bourne Again Shell"), scripts can be in bash, python, perl, ruby, PHP, etc, etc. For example, you might see #!/bin/perl or #!/bin/perl5.

PS: The exclamation mark (!) is affectionately called "bang". The shell comment symbol (#) is sometimes called "hash".

PPS: Remember - under *nix, associating a suffix with a file type is merely a convention, not a "rule". An executable can be a binary program, any one of a million script types and other things as well. Hence the need for #!/bin/bash.

Camilo Sampedro
  • 1,306
  • 1
  • 19
  • 32
paulsm4
  • 114,292
  • 17
  • 138
  • 190
  • 1
    I found out about something else useful, $#. What's that called? – node ninja Jan 23 '12 at 08:09
  • 112
    The shebang is not a *shell* convention, it is interpreted by the *kernel* when handling the `execve(2)` syscall; so the shebang is a *kernel* convention, not a shell one. – Basile Starynkevitch Jan 23 '12 at 08:32
  • 12
    Also, it helps some editors like Vim determine the language for syntax highlighting if the file doesn't have an extension. Without the shebang, Vim will display a bash script the same as plain text file. – Aaron Blenkush Dec 10 '13 at 21:16
  • ps -u cannot list your script file name unless you add shebang. why is this? – Rio Wing Oct 13 '16 at 19:10
  • 1
    It makes me wonder whether you need to add `#!/bin/sh` to things like `.profile` and stuff that runs *onload* – Kellen Stuart Oct 18 '16 at 16:51
  • 3
    I've seen many answers to the question without a real explanation -- but the last part of your answer "_An executable can be a binary program, any one of a million script types and other things as well. Hence the need for #!/bin/bash._" really nailed it – senseiwu Aug 11 '18 at 17:00
  • 7
    So... _hash-bang-slash-bin-slash-bash_? – Bernat Jan 31 '19 at 12:18
  • 1
    `.profile` or `.bashrc` are sourced not executed so do not want to start with #! – Scott Stensland Dec 06 '19 at 13:42
  • Note that "officially" (or historically?) the shebang should start with `#! /`. Note the space between the exclamation mark and the slash. The result is that the first four bytes of scripts all start with the same "magic value": the magic value of a shell script. This value is (was) used by for example a utility like `file` to recognize what a file was. Of course, these days, file etc. recognizes every shell just fine even though most people leave out the space. – Carlo Wood May 13 '20 at 01:56
  • @Carlo Wood - you're correct about "#!" being used as a "magic number" - but mistaken that it's a 32-bit value. Two-byte "magic numbers" aren't uncommon: `"#!" (23 21)`, `"MZ" (4D 5A)`, `"PK" (50 4B)`, etc. etc. – paulsm4 May 14 '20 at 22:03
  • I didn't make it up myself. – Carlo Wood May 18 '20 at 01:21
  • Doesn't the "#" mean it's a comment (sorry for the stupid question, I am really new to this) – Wallflower Dec 25 '21 at 14:15
  • Some times I see people use `#!/bin/bash -ex` twice in the script. Does that make a difference? – Ultrablendz Mar 24 '23 at 13:59
160

To be more precise the shebang #!, when it is the first two bytes of an executable (x mode) file, is interpreted by the execve(2) system call (which execute programs). But POSIX specification for execve don't mention the shebang.

It must be followed by a file path of an interpreter executable (which BTW could even be relative, but most often is absolute).

A nice trick (or perhaps not so nice one) to find an interpreter (e.g. python) in the user's $PATH is to use the env program (always at /usr/bin/env on all Linux) like e.g.

 #!/usr/bin/env python

Any ELF executable can be an interpreter. You could even use #!/bin/cat or #!/bin/true if you wanted to! (but that would be often useless)

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
55

It's called a shebang. In unix-speak, # is called sharp (like in music) or hash (like hashtags on twitter), and ! is called bang. (You can actually reference your previous shell command with !!, called bang-bang). So when put together, you get haSH-BANG, or shebang.

The part after the #! tells Unix what program to use to run it. If it isn't specified, it will try with bash (or sh, or zsh, or whatever your $SHELL variable is) but if it's there it will use that program. Plus, # is a comment in most languages, so the line gets ignored in the subsequent execution.

austin1howard
  • 4,815
  • 3
  • 20
  • 23
  • 2
    If I'm already in bash, does it start another bash instance if it sees #!/bin/bash? What if I'm already in bash and I leave it out? Is there any difference? – node ninja Jan 23 '12 at 07:29
  • 2
    @javascriptninja either way it starts a new bash shell. In the case of bash, there really isn't any difference, as long as you're using bash already. The shebang only really matters if (a) you need to run in something that isn't just a shell, like python or perl, or (b) you don't use the bash shell (ie you use zsh) but you need to run something which requires being run in bash. – austin1howard Jan 23 '12 at 08:20
  • However, in my opinion it's good practice to include the shebang, just so someone reading the code knows what's going on. – austin1howard Jan 23 '12 at 08:22
  • 2
    Wrong: `execve(2)` syscall don't use the `$SHELL` variable. It is the kernel that is interpreting the shebang. – Basile Starynkevitch Jan 23 '12 at 15:29
  • 1
    @BasileStarynkevitch that is correct, the elf loader in kernel interprets the shebang. I was stating that $SHELL would be used if no shebang was provided. – austin1howard Jan 24 '12 at 08:44
  • I was really surprised to find that omitting the `#!` works even for something run from `find -exec` (i.e. not directly from a shell). e.g. with `echo hello` in `/tmp/foo` (executable), strace and `ltrace -f find [file] -exec /tmp/foo {} +` shows that `execvp(3)` succeeds: It first tries `execve(2)`, which of course fails with `ENOEXEC (Exec format error)`, but then it falls back to `execve`ing `/bin/sh` `/tmp/foo`. So your claim that "Unix will try $SHELL" is closer to correct than I assumed, thanks to libc's help. Most programs don't use `execve` directly, but no-#! will break then. – Peter Cordes Jun 20 '16 at 11:36
  • I upvoted this because it explains nicely why I can run bash scripts without the hashbang. I ran `echo $SHELL` and `/bin/bash` was the result. So something I didn't know before. Thanks. – mikelovelyuk Aug 26 '17 at 21:19
22

Every distribution has a default shell. Bash is the default on the majority of the systems. If you happen to work on a system that has a different default shell, then the scripts might not work as intended if they are written specific for Bash.

Bash has evolved over the years taking code from ksh and sh.

Adding #!/bin/bash as the first line of your script, tells the OS to invoke the specified shell to execute the commands that follow in the script.

#! is often referred to as a "hash-bang", "she-bang" or "sha-bang".

Community
  • 1
  • 1
jaypal singh
  • 74,723
  • 23
  • 102
  • 147
20

The operating system takes default shell to run your shell script. so mentioning shell path at the beginning of script, you are asking the OS to use that particular shell. It is also useful for portability.

BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
Balaswamy Vaddeman
  • 8,360
  • 3
  • 30
  • 40
20

The shebang is a directive to the loader to use the program which is specified after the #! as the interpreter for the file in question when you try to execute it. So, if you try to run a file called foo.sh which has #!/bin/bash at the top, the actual command that runs is /bin/bash foo.sh. This is a flexible way of using different interpreters for different programs. This is something implemented at the system level and the user level API is the shebang convention.

It's also worth knowing that the shebang is a magic number - a human readable one that identifies the file as a script for the given interpreter.

Your point about it "working" even without the shebang is only because the program in question is a shell script written for the same shell as the one you are using. For example, you could very well write a javascript file and then put a #! /usr/bin/js (or something similar) to have a javascript "Shell script".

Noufal Ibrahim
  • 71,383
  • 13
  • 135
  • 169
12

It is called a shebang. It consists of a number sign and an exclamation point character (#!), followed by the full path to the interpreter such as /bin/bash. All scripts under UNIX and Linux execute using the interpreter specified on a first line.

Uday Sawant
  • 5,748
  • 3
  • 32
  • 45
4

Bash standards for “Bourne-Again shell” is just one type of many available shells in Linux.

A shell is a command line interpreter that accepts and runs commands.

Bash is often the default shell in most Linux distributions. This is why bash is synonymous to shell.

The shell scripts often have almost the same syntaxes, but they also differ sometimes. For example, array index starts at 1 in Zsh instead of 0 in bash. A script written for Zsh shell won’t work the same in bash if it has arrays.

To avoid unpleasant surprises, you should tell the interpreter that your shell script is written for bash shell. How do you do that?

simply begin your bash script into #!/bin/bash

1

Also you will see some other parameters after #!/bin/bash, for example
#!/bin/bash -v -x
read this to get more idea.
https://unix.stackexchange.com/questions/124272/what-do-the-arguments-v-and-x-mean-to-bash .

star
  • 691
  • 7
  • 12
0

It can be useful to someone that uses a different system that does not have that library readily available. If that is not declared and you have some functions in your script that are not supported by that system, you should declare #/bin/bash. I've ran into this problem before at work and now I just include it as a practice.

Community
  • 1
  • 1
Beardy
  • 83
  • 4
  • 11