What is the preferred Bash shebang (`#!`) for scripts?

I’m wondering if there’s an objectively better bash shebang for most use cases. Options I’ve seen include:

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

I also heard that adding a dash (-) at the end might prevent someone from passing a command to your script. Which shebang is considered best practice and why?

A few notes on the other options:

* #!/bin/sh → Runs in POSIX-compliant mode, not necessarily Bash. Good for portable scripts, but some Bash-specific features won’t work.

  • #!/sh - → Rarely used; the dash is meant to make the shell a login shell, but it’s not needed for most scripts.

Passing a command (like bash -c “…”) is independent of the shebang—don’t rely on the dash to block it.

You might see:

#!/bin/bash

This works if you know the system has Bash installed at /bin/bash.

Slightly faster than env because it doesn’t spawn a new process.

I usually reserve this for controlled environments like my own servers or CI pipelines.

I’ve gone back and forth on this before :sweat_smile:. For most scripts, I use:

#!/usr/bin/env bash

env finds the first bash in the user’s PATH, so it’s more portable across systems.

Useful if bash isn’t in /bin (some Linux distros, macOS, or custom environments).

Works well for scripts shared across multiple machines.