Why do you need to put #!/bin/bash at the beginning of a script file?
Asked Answered
E

11

669

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?

Espy answered 23/1, 2012 at 6:24 Comment(7)
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.Trinidad
It's pronounced "Hash-Bang" or "She-Bang".Admonition
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.Tartuffe
@JFA is there a change in sequence between bash and python , when using !# for python and #! for bash ?Overcritical
@AjeyaAnand no it was a mistype, good catchTartuffe
Further reading: medium.com/@codingmaths/…Agram
... because it's many more there than just a bashLactalbumin
F
547

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.

Footpound answered 23/1, 2012 at 6:26 Comment(15)
I found out about something else useful, $#. What's that called?Espy
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.Sizeable
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.Antonetteantoni
ps -u cannot list your script file name unless you add shebang. why is this?Leges
It makes me wonder whether you need to add #!/bin/sh to things like .profile and stuff that runs onloadWellfed
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 itPsf
So... hash-bang-slash-bin-slash-bash?Achaemenid
.profile or .bashrc are sourced not executed so do not want to start with #!Minier
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.Redan
@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.Footpound
I didn't make it up myself.Redan
Doesn't the "#" mean it's a comment (sorry for the stupid question, I am really new to this)Amberly
Some times I see people use #!/bin/bash -ex twice in the script. Does that make a difference?Rigdon
Boo hiss re: inaccurate verbiage (saying that it's telling the shell vs the kernel what to run).Gwenn
@CarloWood, ...not saying you made it up, but pretty sure you got it from an inaccurate source. I learned it as a 16-bit magic number decades ago.Gwenn
S
162

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)

Sizeable answered 23/1, 2012 at 7:49 Comment(4)
See this question for a discussion of the #!/usr/bin/env hack.Wop
if i want to pass a argument to python how do i do that actually i want to execute #!/usr/bin/env bash -x. How do i do that ?Hwahwan
its simple i myself found it, just add the param after that #!/usr/bin/env bash -xHwahwan
bash is almost always at /bin/bash so your shebang should be #!/bin/bash -xSizeable
G
57

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.

Gravel answered 23/1, 2012 at 6:34 Comment(7)
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?Espy
@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.Gravel
However, in my opinion it's good practice to include the shebang, just so someone reading the code knows what's going on.Gravel
Wrong: execve(2) syscall don't use the $SHELL variable. It is the kernel that is interpreting the shebang.Sizeable
@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.Gravel
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 execveing /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.Apollus
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.Gatha
R
23

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".

Rocker answered 23/1, 2012 at 6:32 Comment(0)
H
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.

Hemipode answered 23/1, 2012 at 6:28 Comment(0)
S
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".

Schlesinger answered 23/1, 2012 at 6:36 Comment(0)
H
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.

Hammett answered 23/1, 2012 at 6:36 Comment(0)
M
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

Mutineer answered 17/4, 2021 at 14:53 Comment(0)
C
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 .

Charity answered 4/4, 2019 at 1:8 Comment(0)
G
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.

Gerladina answered 20/7, 2013 at 20:31 Comment(0)
S
0

#!/bin/bash shebang line is all about making sure your script runs smoothly, with the right interpreter, and is easy to use across different environments. It's a small detail that makes a big difference in scripting.

Shandrashandrydan answered 3/4 at 14:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.