The shell that I normally use is zsh. I have several aliases to enable color in some programs such as ls and grep. I've also set my custom path so that I can execute programs in non-standard place (such as in ~/bin/).

I won't change root's shell to zsh, but I would like to share these setting so that root can have it as well. I find out that zsh is not sourcing /etc/profile. I can source it in /etc/zsh/zprofile, but I would like some other more "proper" way.


I'd create a file /etc/commonprofile and source it in both /etc/profile and /etc/zsh/zprofile. This gives you the opportunity to share common settings and still use bash respectively zsh specific settings and syntax in /etc/profile respectively zprofile.

  • 1
    among other good answers I think this one suits me the best, relatively simple and "clean"
    – phunehehe
    Oct 24 '10 at 12:05
  • what do you mean by "source it" ?
    – Hlung
    May 14 '15 at 5:14
  • @Hlung For loading the shell profile explicility, here the 'source /path/to/.shell_profile' comes. See man page on 'source'.
    – Itachi
    Jun 15 '15 at 6:26

Zsh has an sh compatibility mode which will let it execute POSIX sh code and some bash extensions. As long as you don't use bash features that zsh doesn't have (with the same syntax), you can have the same file sourced by both shells. Use the emulate built-in to put zsh in compatibility mode; with the -L option, the emulation is local to the enclosing function (not the enclosing sourced script).

source_sh () {
  emulate -LR sh
  . "$@"

For things like environment variables, you can use source_sh /etc/profile in /etc/zprofile and source_sh ~/.profile in ~/.zprofile, since the profile files aren't likely to use bash-specific features.

For things like aliases and function definitions, since the shell rc files are likely to contain a lot of things that can't be shared (prompt, key bindings, completion settings, …), use a file like ~/.sh_aliases that is sourced in ~/.bashrc and source_sh'd in ~/.zshrc.

  • 2
    There should be a way to say "automatically upvote all answers by Gilles". This would save me quite some time. No really, your answers rock. Always accurate, well written and comprehensive.
    – fschmitt
    Oct 23 '10 at 21:14
  • @fschmitt: I agree. And you can see it's not even edited! This hint provided here is really good. Dec 16 '10 at 20:11
  • Better to source in the respective env files imo. Eg.. Zshenv or bash_env
    – RichieHH
    Dec 5 '20 at 20:13
  • @RichieHH Despite their names, the *env scripts are not a good place to set environment variables, because they are read by every script — but only scripts run by that particular shell. So if a program runs a script and expects it to have a certain environment, it might stop working, if your *env script happens to modify a variable that the program cares about. Dec 5 '20 at 22:30

What about a simple symlink?

ln -s /etc/profile /etc/zsh/zprofile

You can also append something like this if you need some conditional initialization:

#Determine our shell without using $SHELL, which may lie
if test -f /proc/mounts; then
   case $(/bin/ls -l /proc/$$/exe) in
        *bash) shell=bash ;;
        *dash) shell=dash ;;
        *ash)  shell=ash ;;
        *ksh)  shell=ksh ;;
        *zsh)  shell=zsh ;;
  • Hmm but I don't think this will be any cleaner than sourcing it. Is there a file that both zsh and bash will read?
    – phunehehe
    Oct 23 '10 at 15:38
  • what makes you think that sourcing or creating a symlink is not a "clean" solution?
    – echox
    Oct 23 '10 at 19:40
  • I just meant to say if needed, I'd like to source the file rather than to manage the symlink. I don't want to create a lot of dependency between files.
    – phunehehe
    Oct 24 '10 at 6:24
  • 1
    A more portable alternative to /bin/ls -l /proc/$$/exe is ps -o comm= -p $$. This isn't fully reliable because some shells behave differently depending on how they were invoked; in practice simply testing $0 in .profile is likely to be a better indication. But most shells that offer useful features (bash, ksh, zsh) can be simply recognized (and their version identified, which is a big plus) by testing some variables: $BASH, $BASH_VERSION, $BASH_VERSINFO; $KSH_VERSION, ${.sh.version}; $ZSH_VERSION. Nov 20 '10 at 0:10
  • echox, your case statement does not correctly detect zsh4 #Determine our shell without using $SHELL, which may lie shell="sh" if test -f /proc/mounts; then case $(/bin/ls -l /proc/$$/exe) in bash) shell=bash ;; *dash) shell=dash ;; *ash) shell=ash ;; *ksh) shell=ksh ;; *zsh) shell=zsh ;; #matches zsh4 esac fi
    – Bryan Hunt
    Jan 26 '11 at 19:28

As regards variables, I have the impression that you are missing modules & modulefiles [1]. Once you start doing so, it will be easy to create common profiles for various shells (incl. bash & zsh), python, perl and even more environments, all from the convenience of a single module file.

It is also possible to define aliases in the same way; however, you will quickly find that aliases do not get inherited very well between successive shells and may need workarounds.

[1] http://en.wikipedia.org/wiki/Environment_Modules_(software)

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.