CECI N'EST PAS UNE -EPIPE

Notes from paultag

Using env(1) in the shebang

by

Paul Tagliamonte

Some of you out there may have tried to pass flags to a script that was being invoked via /usr/bin/env in the shebang (#!), such as python. You might recall an error such as:

/usr/bin/env: python -d: No such file or directory

This error is super annoying, so I went about trying to figure out how I can pass arguments to python (or even things like ipython or bpython).

The idea is we can abuse the concept of a polygot to shim in some things we care about.

Implementation

Let’s take a look at a quick script I hacked up to use bpython with a pre-made script that drops into interactive work.

#!/bin/sh
"""":
exec /usr/bin/env bpython -i $0 $@
"""
import hy
print "Hython is now importable!"

Let’s step through this slowly. First, the bits the bash sees:

#!/bin/sh
"""":
exec /usr/bin/env bpython -i $0 $@

Which will cause bpython to reload the file, which looks like the following to Python:

#!/bin/sh
"""":
exec /usr/bin/env bpython -i $0 $@
"""
import hy
print "Hython is now importable!"

Where Python can now ignore the docstring. Magic!