Because interpreters such as zsh, bash, python, perl may be located in different places on the filesystem, scripts often have a shebang that uses
env for portability, e.g.
#!/usr/bin/env zsh. However, as http://en.wikipedia.org/wiki/Shebang_(Unix)#Portability explains, many systems including Linux don’t allow the passing of arguments to the interpreter.
Often, I’d like to do something like
#!/usr/bin/env zsh -f to prevent my script to ever read my
~/.zshenv, or I’d like to do
#!/usr/bin/env perl -w, etc. This works on OS X, but not on Linux.
What is the workaround for that? Can I have the best of both worlds: portability and arguments for the interpreter? If possible, give a general workaround that works for all interpreters, not just zsh.
Here’s an inline solution to work around the portability problem for ZSH.
if [ -z "$IN_ZSH" ]; then export IN_ZSH=1 exec zsh -f "$0" "$@" fi ## Your ZSH script here
Some other methods to try include
- Passing env variables via /usr/bin/env which modify the behavior the same as
--optionssuch as doing
#! /usr/bin/env POSIXLY_CORRECT=1 bash
- Using clever commenting tricks, such as how this script starts out using SH but invokes TCL on the same script
#! /bin/sh # TCLBIN=/usr/bin/tclsh; exec $TCLBIN "$0" "$@" # Execute the rest via tclsh set argc
- Setting the option once in the interpreter, if the
--optionsbeing passed in do not affect the load behavior
#! /usr/bin/env bash # Exit if any error detected set -e
- For perl, if you’re able to use newer versions, this may work in lieu of -w:
#! /usr/bin/env perl use warnings;
- Using a bootstrap
invoke.shscript instead of /usr/bin/env to use your PATH, calling with
/path/to/invoke.sh scriptwith your script starting with
#! zsh -f
#! /bin/sh SCRIPT=$1 shift 1 cmd=`sed -n -e 's:#! ?::' -e '1p' $SCRIPT` exec $cmd $SCRIPT