Skip to content
C.W.K.
Stream
Lesson 01 of 12 · published

The Shebang Line

~8 min · shebang, interpreter

Level 0Window Tourist
0 XP0/95 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete

The two characters that tell the kernel what to do

When you run ./script.sh, the kernel reads the first two bytes. If they're #! (the shebang), the rest of the first line is the path to an interpreter. The kernel runs that interpreter with your script as the argument.

The portable shape

#!/usr/bin/env bash
#!/usr/bin/env zsh
#!/usr/bin/env python3
#!/bin/sh

/usr/bin/env looks the binary up on PATH, so your script works on any box that has bash somewhere in PATH — even when Apple's bash is at /bin/bash and Linux's is /usr/bin/bash. Hard-coding /bin/bash works on macOS but breaks on minimal Linux containers.

Make it executable

chmod +x script.sh
./script.sh

Without chmod +x, the kernel refuses to launch. You can still run it as bash script.sh — that bypasses the shebang and uses bash explicitly.

Don't lie about the interpreter

Shebang says one thing, body uses another? Bugs. If the body uses [[ ]] (bash/zsh-only) but shebang is #!/bin/sh, POSIX sh might choke. Pick the interpreter that matches the body and stick to it.

Flexibility and reproducibility pull in opposite directions

/usr/bin/env bash follows PATH, which is convenient for developer-installed Bash versions. A deployment that requires one verified interpreter may be safer with a controlled absolute path.

The caller can override the shebang

Running bash script.sh asks that Bash to read the file directly. Executable permission and the shebang matter when the file itself is invoked.

The first line is the contract, not the extension

A .sh suffix does not select syntax. When the file is executed directly, the shebang identifies the interpreter; when a caller runs bash file, that caller overrides it.

Code

A safe portable header·bash
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
echo "running on $(uname -s)"

External links

Exercise

Write hello.sh with #!/usr/bin/env bash and echo hi. chmod +x hello.sh; ./hello.sh. Then change the shebang to #!/usr/bin/env zsh and rerun — same output, different interpreter.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.