I am trying to make this script work which was initially written by one of my coworkers for bash shells. The plan is to source it in the zsh shell. As far as I understand it, this script allows to access the helper scripts that are held in this dir across the terminal. However, when I execute just this bit, I keep getting the error message.

I have tried following solutions of some of the already answered questions such as substituting ${BASH_SOURCE[0]} with ${(%):-%N or ${(%):-%x}From here.


if [[ "$PATHNAME" != "$0" ]]; then
    export EXAMPLE_DIR=$(dirname $(dirname $(realpath ${BASH_SOURCE[0]})));
    >&2 echo "This script should be sourced, not executed in a subshell";

I do not understand why do I keep getting the error and I would really like to understand what is the issue with it. Any help or links for reading extremely appreciated!

  • "the error message"? Which error message? – muru Jun 24 '20 at 2:36
  • "This script should be sourced, not executed in a subshell" – Marlon Richert Jun 24 '20 at 10:22

You're getting the error because $_ is not the same in Zsh as it is in Bash.

In Bash:

$_ (an underscore), at shell startup, is set to the absolute pathname used to invoke the shell or shell script being executed as passed in the environment or argument list. Subsequently, expands to the last argument to the previous simple command executed in the foreground, after expansion. Also set to the full pathname used to invoke each command executed and placed in the environment exported to that command. When checking mail, this parameter holds the name of the mail file.

You need to rewrite that block like this:

if [[ -z ${(M)zsh_eval_context:#file} ]]; then
  print -u2 $0:A should be sourced, not executed in a subshell.
  return 1
export EXAMPLE_DIR=$0:A:h:h

$zsh_eval_context will contain the word file when the code is being read directly from a file, such as when using the source builtin.

${(M)zsh_eval_context:#file} evaluates to a zero-length string if $zsh_eval_context does not contain the word file.

print -u2 prints to standard error.

$0 is the file name of the sourced script. :A (which stands for "Absolute") turns the file name into an absolute path and then passes the result through realpath (if available) to resolve symbolic links. :h (which stands for "head") does the same as dirname, but without actually needing that external command.

  • 1
    hi @Marlon Richert, I am extremely grateful for your response! It is explained amazingly, and what is more important - educational and effective! Thank you very much, really appreciated. – Iwo Pieniak Jul 15 '20 at 13:06
  • You’re welcome. Glad you like it. 🙂 – Marlon Richert Jul 21 '20 at 8:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.