25

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.

4 Answers 4

20

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.

3
  • 1
    among other good answers I think this one suits me the best, relatively simple and "clean"
    – phunehehe
    Oct 24, 2010 at 12:05
  • what do you mean by "source it" ?
    – Hlung
    May 14, 2015 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, 2015 at 6:26
19

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.

4
  • 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, 2010 at 21:14
  • @fschmitt: I agree. And you can see it's not even edited! This hint provided here is really good. Dec 16, 2010 at 20:11
  • Better to source in the respective env files imo. Eg.. Zshenv or bash_env
    – RichieHH
    Dec 5, 2020 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, 2020 at 22:30
4

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
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 ;;
    esac
fi
5
  • 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, 2010 at 15:38
  • what makes you think that sourcing or creating a symlink is not a "clean" solution?
    – echox
    Oct 23, 2010 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, 2010 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, 2010 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, 2011 at 19:28
0

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)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .