7

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.

1 Answer 1

6

Here's an inline solution to work around the portability problem for ZSH.

#! /bin/sh

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 --options such 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 --options being 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.sh script instead of /usr/bin/env to use your PATH, calling with /path/to/invoke.sh script with your script starting with #! zsh -f
    #! /bin/sh

    SCRIPT=$1
    shift 1
    cmd=`sed -n -e 's:#! \?::' -e '1p' $SCRIPT`
    exec $cmd $SCRIPT
4
  • For the zsh-specific workaround, I prefer the following myself [ "x$ZSH_VERSION" = "x" ] && exec zsh -f "$0" "$@"
    – huyz
    May 10, 2011 at 6:55
  • Thanks for the research. I didn't know that ` #! /usr/bin/env POSIXLY_CORRECT=1 bash` would work.
    – huyz
    May 10, 2011 at 6:57
  • 1
    I guess there is no single "general solution" that no one else can offer. So I'll accept your answer. Hopefully someday Linux gets with the program.
    – huyz
    Jul 5, 2011 at 6:33
  • #! /usr/bin/env POSIXLY_CORRECT=1 bash doesn't work as it is as though you wrote /usr/bin/env "POSIXLY_CORRECT=1 bash" script at the shell.
    – r3m0t
    Apr 4, 2013 at 20:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .