Search code examples
bashzsh

Running bash script, results from zsh different than bash, even though script has bash shebanged


I have the following script, test.sh, that if I call it from bash, works, but if I call it from zsh, doesn't, even though it has a bash shebang at the top

If I call it from zsh, I get the following error. Anyone know why?

$ . scripts/test.sh
scripts/test.sh:14: = not found

The line it's complaining about is:

if [ "$SOURCED" == "0" ]

test.sh

#!/usr/bin/env bash
(return 0 2>/dev/null) && SOURCED=1 || SOURCED=0

function showHelp(){
  local ME;
  ME=$(basename "$0")
  echo
  echo "This command needs to be run like so:"
  echo "$ . $ME "
  echo
}

# exit if not sourced or called from another script
if [ "$SOURCED" == "0" ]
then
  if [ -z "$1" ]
  then
    showHelp
    exit;
  fi
fi

Solution

  • . does not mean "run this file with bash". It means execute the contents in the current shell.

    Further, the [ built-in in zsh, unlike the one in bash, does not accept == as a string comparision operator. You have to use =. (As an aside, you should use [ ... = ... ] in bash as well, to avoid confusion.) If you want to use ==, use [[ "$SOURCED" == "0" ]] instead.

    The shebang is only used if you execute the script as the command itself, for example ./test.sh or /some/absolute/path/to/test.sh or test.sh (if test.sh is in a directory on your PATH).

    For whatever historical reason, . was chosen for the command name, despite the potential for confusion with . as the name of the current directory (. test.sh vs ./test.sh vs . ./test.sh). Though POSIX does not require a more readable synonym, most modern shells provide source as an (near) equivalent. (Because it is not standard, though, the behavior of source can vary from shell to shell. I believe . and source are equivalent in bash, but there is a slight difference regarding PATH lookup of its argument between the two in zsh.)