I try to build scripts that work everywhere and always. For this I use a custom-built python, which is always in the parent directory relative to the script.
This way I could load my package on an USB-stick and it would work everywhere, regardless of where the stick is mounted and whether python is installed or not.
However, when I use
#!../python
then it works only when the script gets invoked from its directory, which is of course not acceptable.
Is there a way to do this or is this impossible in the current shebang-mechanism?
There is a healthy set of multi-line shebang scripts on this page for a lot of languages, example:
#!/bin/sh
"exec" "`dirname $0`/python" "$0" "$@"
print copyright
And if you want one-line shebang, this answer (and question) explains the issue in the details and suggests the following approaches using additional scripts inside the shebang:
#!/usr/bin/awk BEGIN{a=ARGV[1];sub(/[a-z_.]+$/,"python",a);system(a"\t"ARGV[1])}
#!/usr/bin/perl -e$_=$ARGV[0];exec(s/\w+$/python/r,$_)
update from 11Jan21:
env
utility:$ env --version | grep env
env (GNU coreutils) 8.30
$ env --help
Usage: env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]
Set each NAME to VALUE in the environment and run COMMAND.
Mandatory arguments to long options are mandatory for short options too.
-i, --ignore-environment start with an empty environment
-0, --null end each output line with NUL, not newline
-u, --unset=NAME remove variable from the environment
-C, --chdir=DIR change working directory to DIR
-S, --split-string=S process and split S into separate arguments;
used to pass multiple arguments on shebang lines
So, passing -S
to env will do the job now
Expanding @Anton's answer so as not to fail on spaces and other special characters in the path and to explain a bit more about the magic.
#!/bin/sh
"true" '''\'
exec "$(dirname "$(readlink -f "$0")")"/venv/bin/python "$0" "$@"
'''
__doc__ = """You will need to deliberately set your docstrings though"""
print("This script is interpretable by python and sh!")
This clever script is comprehendable by both sh and python. Each of which react to it differently. The first 2 lines after the shebang are interpreted by sh and cause it to hand over exec to a relative python binary (supplied with the same command line arguments). These same lines are safely discarded by python since they amount to a string ("true") followed by a multi-line string (''').
A little more about this subject can be read here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With