Start zsh with a custom zshrc
From the man pages:
STARTUP/SHUTDOWN FILES
Commands are first read from /etc/zshenv; this cannot be overridden. Subsequent be‐
haviour 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, com‐
mands 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.
When a login shell exits, the files $ZDOTDIR/.zlogout and then /etc/zlogout are read.
This happens with either an explicit exit via the exit or logout commands, or an
implicit exit by reading end-of-file from the terminal. However, if the shell termi‐
nates due to exec'ing another process, the logout files are not read. These are also
affected by the RCS and GLOBAL_RCS options. Note also that the RCS option affects
the saving of history files, i.e. if RCS is unset when the shell exits, no history
file will be saved.
If ZDOTDIR is unset, HOME is used instead. Files listed above as being in /etc may
be in another directory, depending on the installation.
As /etc/zshenv is run for all instances of zsh, it is important that it be kept as
small as possible. In particular, it is a good idea to put code that does not need
to be run for every single shell behind a test of the form `if [[ -o rcs ]]; then
...' so that it will not be executed when zsh is invoked with the `-f' option.
so you should be able to set the environment variable ZDOTDIR
to a new directory to get zsh to look for a different set of dotfiles.
As the man page suggests, RCS
and GLOBAL_RCS
are not paths to rc files, as you are attempting to use them, but rather options you can enable or disable. So, for instance, the flag --rcs
will enable the RCS
option, causing zsh to read from rc files. You can use the following command-line flags to zsh to enable or disable RCS
or GLOBAL_RCS
:
--globalrcs
--rcs
-d equivalent to --no-globalrcs
-f equivalent to --no-rcs
To answer your other question:
is it possible to start zsh, run "source /path/to/file", then stay in the same zsh session?
Yes, this is pretty easy according to the above directions. Just run zsh -d -f
and then source /path/to/zshrc
.
while with ZDOTDIR, you can tell zsh
to interpret a file called .zshrc
in any directory of your choosing, having it interpret any file of your choosing (not necessarily called .zshrc
) proves quite difficult.
In sh
or ksh
emulation, zsh
evaluates $ENV
; so you could add emulate zsh
at the top of your /path/to/file
and do:
ssh -t host 'zsh -c "ARGV0=sh ENV=/path/to/file exec zsh"'
Another very convoluted approach could be:
ssh -t host 'PS1='\''${${functions[zsh_directory_name]::="
set +o promptsubst
unset -f zsh_directory_name
unset PS1
. /path/to/file
"}+}${(D):-}${PS1=%m%# }'\' exec zsh -o promptsubst -f
That one deserves a bit of an explanation.
${foo::=value}
is a variable expansion that actually sets $foo
. $functions
is a special associative array that maps function names to their definitions.
With the promptsubst
option, variables in $PS1
are expanded. So, upon the first prompt, the variables in that PS1 will be expanded.
The zsh_directory_name
function is a special function that helps expanding the ~foo
to /path/to/something
and the reverse. That's used for instance with %~
in the prompt so that if the current directory is /opt/myproj/proj/x
you can display it as ~proj:x
by having zsh_directory_name
do the mapping proj:x
<=> /opt/myproj/proj/x
. That's also used by the D
parameter expansion flag. So if one expands ${(D)somevar}
, that zsh_directory_name
function will be called.
Here, we're using ${(D):-}
, ${:-}
, that is ${no_var:-nothing}
expands to nothing
if $no_var
is empty, so ${(D):-}
expands to nothing while calling zsh_directory_name
. zsh_directory_name
has previously been defined as:
zsh_directory_name() {
set +o promptsubst
unset -f zsh_directory_name
unset PS1; . /path/to/file
}
That is, upon the first PS1 expansion (upon the first prompt), ${(D):-}
will cause the promptsubst
option to be unset (to cancel the -o promptsubst
), zsh_directory_name()
to be undefined (as we want to run it only once) $PS1
to be unset, and /path/to/file
to be sourced.
${PS1=%m%# }
expands (and assigns $PS1
) to %m%#
unless PS1 was already defined (for instance by /path/to/file
after the unset
), and %m%#
happens to be the default value of PS1
.