The problem lies in how you're calling the .
special builtin:
exec /bin/sh -c '. vars.sh; /usr/bin/fish'
In sh
, if the argument doesn't contain any /
, .
searches for the file in $PATH
. So above, it would look for vars.sh
in $PATH
instead of the current directory as you intended.
Also, .
being a special builtin, its failure causes the shell to exit (when not interactive), so the next command (here fish
) is not executed which is why your terminal emulator window goes away without a fish
prompt.
That can be prevented by calling .
as command .
which removes the special attribute of special builtins.
Note that the behaviour of bash
(the sh
implementation of the GNU project) is different in that regard when not in POSIX mode (when not called as sh
, nor with --posix
, and when the environment doesn't contain POSIXLY_CORRECT=
nor SHELLOPTS=posix
):
bash
's .
doesn't cause the shell to exit upon failure and it searches for slash-less argument in the current directory if it can't find it in $PATH
.
In any case, POSIX mode or not, if you want the vars.sh
in the current directory, you need the ./vars.sh
syntax. So it's
exec sh -c 'command . ./vars.sh; exec fish'
Best Answer
The same thing happens in a simpler form:
If you now run
trythis
andecho $foo
, it is not set either. That's because fish's-x
by itself doesn't change the scope of the variable, which is by default local to the function unless it exists globally or universally already.Try:
Where the
g
is for global. This makes the variable work like a normal POSIXexport
ed value. It's interesting that it works the same way witheval
as it would with just plainset
; if you use that line sansg
straight on the command line,$FOO
is set, soeval
and process substitution()
have not introduced a new scope or subshell, and when executed that way within a function, the scope of the function applies.