shebang: use interpreter relative to the script path

Robby75 picture Robby75 · Nov 20, 2013 · Viewed 10.9k times · Source

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?

Answer

Anton picture Anton · Oct 20, 2015

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:

Using AWK

#!/usr/bin/awk BEGIN{a=ARGV[1];sub(/[a-z_.]+$/,"python",a);system(a"\t"ARGV[1])}

Using Perl

#!/usr/bin/perl -e$_=$ARGV[0];exec(s/\w+$/python/r,$_)

update from 11Jan21:

Using updated 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