Shebang Explained: #! in Bash and Shell Scripts

By 

Updated on

6 min read

Bash Shebang

When you run a script as an executable file, the operating system needs to know which program should read it. That instruction is usually written on the first line of the file as a shebang, which starts with #! followed by an interpreter path.

A shebang can point to Bash, a POSIX shell, Python, Perl, Node.js, AWK, or another interpreter. This guide explains how shebang lines work in general, then shows how to choose the right Bash shebang for shell scripts.

What Is a Shebang?

A shebang is the interpreter directive at the top of an executable script. It tells the kernel which program to use when you run the file directly, such as ./script.sh.

For example, this shebang tells the system to run the script with Bash:

sh
#!/bin/bash

The #! characters are sometimes called hashbang, sharp-bang, or pound-bang. In day-to-day shell scripting, shebang is the most common name.

If the script is not executable and you run it by passing it to an interpreter, the shebang is not used:

Terminal
bash script.sh

In that case, bash is already the interpreter.

Shebang Syntax

The shebang line takes the following form:

sh
#!interpreter [arguments]
  • The shebang must be the first line in the script.
  • It must start with #!.
  • Whitespace after #! is optional, but most scripts omit it.
  • The interpreter is usually an absolute path, such as /bin/sh or /bin/bash.
  • Interpreter arguments are optional.

Common examples include:

  • #!/bin/bash - Uses bash to parse the file.
  • #!/usr/bin/env perl - Uses the env command to find the path to the perl executable.
  • #!/usr/bin/env python3 - Executes the file using the python3 binary.

Common Shebang Lines

ShebangInterpreter
#!/bin/shPOSIX shell
#!/bin/bashBash using an absolute path
#!/usr/bin/env bashBash found through $PATH
#!/usr/bin/env python3Python 3
#!/usr/bin/env nodeNode.js
#!/usr/bin/env perlPerl
#!/usr/bin/env rubyRuby
#!/usr/bin/awk -fAWK

Use the shebang that matches the language and syntax used in the file. A script that uses Bash arrays, [[ ]], or brace expansion should not use #!/bin/sh.

Bash Shebang: /bin/bash vs /usr/bin/env bash

If a shebang is not specified and you run the script with ./script.sh, the kernel’s execve() call fails to find an interpreter and the calling shell attempts to run it as a shell script. In practice, this means the script is interpreted by /bin/sh, which may not support Bash-specific features. To ensure that your script is always interpreted with Bash, you need to specify the executable path using a shebang.

There are two ways to set the interpreter:

  1. Using the absolute path to the bash binary:

    sh
    #!/bin/bash
  2. Using the env utility:

    sh
    #!/usr/bin/env bash

The advantage of the second approach is that it searches for the bash executable in the user’s $PATH environment variable. If there is more than one path to bash, the first one found will be used. This makes scripts more portable across systems where Bash may not be installed at /bin/bash (such as FreeBSD or NixOS).

Passing Options to the Interpreter

When using the absolute path, you can pass options directly to the interpreter. For example, to run the script in debug mode:

sh
#!/bin/bash -x

When using env, you cannot pass options on the shebang line in the traditional way. Instead, use set inside the script:

sh
#!/usr/bin/env bash
set -x

On systems with coreutils 8.30+ (2018), you can use env -S to split arguments:

sh
#!/usr/bin/env -S bash -x

#!/bin/sh vs #!/bin/bash

These two shebangs are not interchangeable:

  • #!/bin/sh invokes the system’s POSIX-compliant shell. On Debian and Ubuntu, this is typically dash, a lightweight shell that lacks many Bash features.
  • #!/bin/bash invokes Bash specifically, giving you access to arrays, [[ ]] tests, {1..10} brace expansion, and other Bash-only features.

Use #!/bin/sh when your script only uses POSIX syntax and you want maximum portability. Use #!/bin/bash when your script relies on Bash-specific features.

Example Script

Create a simple script that uses a shebang and prints “Hello, World”. Open your text editor and create a file called hello_world:

Terminal
nano hello_world
hello_worldsh
#!/bin/bash

echo "Hello, World"

To be able to run the script without specifying the interpreter from the command line, you need to make the file executable :

Terminal
chmod +x hello_world

Now you can run the script by typing ./ followed by the script name:

Terminal
./hello_world
output
Hello, World

Overriding the Shebang

If for some reason you want to override the interpreter set in the shebang line, run the script by explicitly specifying the desired shell.

For example, to run a script that has #!/bin/sh specified in the shebang line using the bash shell, you would type:

Terminal
bash hello_world

Note that overriding the shell interpreter is not recommended, as it may lead to unexpected behavior.

Troubleshooting

bad interpreter: No such file or directory
The interpreter path in the shebang does not exist, or the file uses Windows CRLF line endings. Check the first line with head -n 1 script.sh, then verify the interpreter with command -v bash or ls -l /bin/bash.

/bin/bash^M: bad interpreter
The script was saved with Windows line endings, so Linux reads the carriage return as part of the interpreter path. Convert the file to Unix line endings with dos2unix script.sh or sed -i 's/\r$//' script.sh.

The script uses the wrong Bash path
Some systems use /bin/bash, while others may have Bash in another location. Check the path with command -v bash. If you need a more portable Bash shebang, use #!/usr/bin/env bash.

Bash syntax fails when the script runs with sh
If the script uses Bash-only syntax such as arrays, [[ ]], or brace expansion, use #!/bin/bash or #!/usr/bin/env bash. Running the same file with sh script.sh overrides the shebang and may fail.

Permission denied when running ./script.sh
The file is not executable. Add execute permission with chmod +x script.sh, then run it again with ./script.sh.

Quick Reference

TaskCommand / Syntax
Shebang syntax#!interpreter [arguments]
Bash shebang (absolute)#!/bin/bash
Bash shebang (portable)#!/usr/bin/env bash
POSIX shell shebang#!/bin/sh
Python 3 shebang#!/usr/bin/env python3
Pass options (absolute)#!/bin/bash -x
Pass options (env)#!/usr/bin/env -S bash -x
Make script executablechmod +x script.sh
Run script./script.sh
Override interpreterbash script.sh
Find Bash pathcommand -v bash

FAQ

What does a shebang mean?
A shebang tells the operating system which interpreter should run an executable script. It starts with #! and is followed by the interpreter path.

What does #!/bin/bash mean?
It tells the operating system to use the Bash interpreter at /bin/bash to execute the script.

Should I use #!/bin/bash or #!/usr/bin/env bash?
Use #!/usr/bin/env bash for portability. It searches $PATH for Bash, which works across systems where Bash is not at /bin/bash. Use the absolute path when you need to pass interpreter options directly on the shebang line.

What happens if I omit the shebang?
The kernel cannot determine the interpreter, so the calling shell attempts to run the script itself. This typically results in the script being interpreted by /bin/sh, which may not support Bash-specific syntax.

Can I use a shebang with Python or other languages?
Yes. Use #!/usr/bin/env python3 for Python, #!/usr/bin/env node for Node.js, #!/usr/bin/env perl for Perl, and so on.

Conclusion

The shebang (#!) tells the operating system which interpreter to use when executing a script. Use #!/bin/bash or #!/usr/bin/env bash for Bash scripts, and choose a different interpreter when the script is written for another language. To learn all the ways to execute scripts, see our guide on how to run a Bash script .

Tags

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page