Shebang Explained: What #!/usr/bin/env Does
Learn what the shebang line does in scripts and how to use it with zsh, bash, python, and swift.
The #!/usr/bin/env swift line at the top of a script file is called a shebang (or hashbang). It tells your system which interpreter should execute the code.
Anatomy of the Shebang
1
#!/usr/bin/env swift
| Part | Purpose |
|---|---|
#! | Signal to the kernel: “This is a script” |
/usr/bin/env | Utility that searches PATH for the program |
swift | The interpreter to use (swift, python, bash, zsh) |
Why Use /usr/bin/env?
| Method | Example | Behavior |
|---|---|---|
| Direct Path | #!/usr/bin/swift | Breaks if Swift is installed elsewhere |
| Env Path | #!/usr/bin/env swift | Finds Swift anywhere in PATH |
Using env makes scripts portable. If someone installs Swift via Homebrew (/opt/homebrew/bin) or a version manager, the script still works.
Examples by Language
Bash Script
1
2
3
4
#!/usr/bin/env bash
echo "Running with Bash"
echo "Current shell: $BASH_VERSION"
Zsh Script
1
2
3
4
5
6
#!/usr/bin/env zsh
echo "Running with Zsh"
# Zsh arrays start at index 1
my_list=("Apple" "Banana")
echo "First item: $my_list[1]"
Python Script
1
2
3
4
5
#!/usr/bin/env python3
import sys
print(f"Python version: {sys.version}")
print("Hello from Python!")
Swift Script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env swift
import Foundation
// Access command line arguments
let args = CommandLine.arguments
if args.count > 1 {
print("Hello, \(args[1])!")
} else {
print("Hello, World!")
}
// Use Foundation APIs
let currentDir = FileManager.default.currentDirectoryPath
print("Running in: \(currentDir)")
Running Scripts
Make the script executable, then run it directly.
1
2
chmod +x myscript.swift
./myscript.swift "iOS Developer"
Output:
1
2
> Hello, iOS Developer!
> Running in: /Users/mehmet/Dev
How It Works
When you execute ./myscript.swift:
- The kernel reads the first two bytes (
#!) - It identifies the file as a script, not a binary
- It reads the interpreter path from the shebang line
- It launches the interpreter and passes the script as input
The command ./myscript.swift becomes swift myscript.swift automatically.
Quick Reference
| Language | Shebang |
|---|---|
| Bash | #!/usr/bin/env bash |
| Zsh | #!/usr/bin/env zsh |
| Python 3 | #!/usr/bin/env python3 |
| Node.js | #!/usr/bin/env node |
| Swift | #!/usr/bin/env swift |
For Swift scripts with external dependencies, consider using swift-sh which allows importing Swift packages directly in script files.
☕ Support My Work
If you found this post helpful and want to support more content like this, you can buy me a coffee!
Your support helps me continue creating useful articles and tips for fellow developers. Thank you! 🙏