You've probably seen the #!/usr/bin/env -S uv run
pattern popularized by Simon Willison.
One issue I've had with it: When "upgrading" scripts to get their own pyproject.toml, I can't run them from a different directory anymore!
E.g. this works:
./my_script.py
This doesn't:
some_dir/my_script.sh
This special, but longer, shebang header allows us to do that.
It works like this:
- The first line is a shebang executing the file as a regular old POSIX script with /bin/sh.
- A comment follows - this is ignored by sh (and also python)
- Here comes the magic: We start a python block comment.
- in Bash land, we just gave an empty string (
""
), followed by the start of a string ("
). - to make bash happy, we finish off with
:"
- turning that "start of a string" into "please execute
:
" - which is an alias for "true"`, or a no-op command returning 0
- in Bash land, we just gave an empty string (
- Now, we just tell bash to run
uv
, but with--project $(dirname $0)
, so that UV knows where to search for a pyproject file. - We use
exec
to replace the runningsh
, so that signals and return codes are followed - We use
set -eu
to error out if any errors occur before uv takes over
- unset variables
uv
not being installed, etc.
Tested on
- macOS
- Debian (Bookworm)
Probably doesn't work on Windows, unless you're using WSL or Git-Bash.