Why is the $PATH different in the executed script

zsh

echo $PATH inside gnome terminal:

/home/pc/less.js/bin:/home/pc/local/bin:/home/pc/local/bin:/home/pc/.rvm/gems/ruby-1.9.2-head/bin:/home/pc/.rvm/gems/ruby-1.9.2-head@global/bin:/home/pc/.rvm/rubies/ruby-1.9.2-head/bin:/home/pc/.rvm/bin:/usr/local/bin:/home/pc/local/bin:/usr/lib64/mpi/gcc/openmpi/bin:/home/pc/bin:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/X11R6/bin:/usr/games:/usr/lib64/jvm/jre/bin:/home/pc/Programming/Software/tup:/home/pc/Programming/Libraries/depottools:/home/pc/Programming/Libraries/apache-maven-3.0.4/bin

From inside this script:

#!/bin/zsh
echo $PATH
while inotifywait -e modify /home/pc/vbox-shared/less; do
    lessc custom.less > /home/pc/vbox-shared/less/custom.css
done

/usr/lib64/mpi/gcc/openmpi/bin:/home/pc/bin:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/X11R6/bin:/usr/games:/usr/lib64/jvm/jre/bin

As you can see, I modified my .zshrc file with this:

export PATH=/home/pc/less.js/bin:$PATH

Why does it not work in the script when executed as a file? The problem is that the lessc command is not being found.

Best Answer

The script is run using /bin/zsh, which is not an interactive or login shell and doesn't load this file. From man zsh, emphasis mine:

Commands are first read from /etc/zshenv; this cannot be overridden. Subsequent behaviour is modified by the RCS and GLOBAL_RCS options; the former affects all startup files, while the second only affects global startup files (those shown here with an path starting with a /). If one of the options is unset at any point, any subsequent startup file(s) of the corresponding type will not be read. It is also possible for a file in $ZDOTDIR to re-enable GLOBAL_RCS. Both RCS and GLOBAL_RCS are set by default.

Commands are then read from $ZDOTDIR/.zshenv. If the shell is a login shell, commands are read from /etc/zprofile and then $ZDOTDIR/.zprofile. Then, if the shell is interactive, commands are read from /etc/zshrc and then $ZDOTDIR/.zshrc. Finally, if the shell is a login shell, /etc/zlogin and $ZDOTDIR/.zlogin are read.

The script inherits the environment from where it's called, and if this isn't another (interactive) shell, it won't contain the preferences you set in .zshrc.

You can set the PATH where it applies globally (e.g. /etc/zshenv), set it explicitly in the script directly, or change the shebang script header to run /bin/zsh -i instead, making it load .zshrc (quoting man zsh: Force shell to be interactive. It is still possible to specify a script to execute.).

Alternatively, just specify the full path to the program that isn't on the default PATH, e.g. /home/pc/less.js/bin/lessc.

Related Question