9

This question is of course related, but different to the one about executing a command.

That questions’ solutions involve either starting a subshell – which isn’t possible due to the requirement of sourcing instead of executing – or modifying your ~/.zshrc, which isn’t possible if you want to distribute a script that does it. (Or rather modifying the user’s config files is a thing you just don’t do)

The problem is that with zsh there is no --init-file parameter like bash has (the first time ever i saw bash having a feature that zsh hasn’t)

I’ll provide an answer with my question, but it’s reeeaaallly ugly, and I hope someone knows a trick to circumvent it!

5
  • 1
    If you are distributing a script, can't you just add the commands to the top of the script (or at least a source command to source the appropriate file). I think I'm missing the rationale for the question.
    – chepner
    May 4, 2013 at 16:52
  • No, the script should be sourced from inside a shell that has some environment variables set, after the user’s rc files have been sourced. all that automatically. May 5, 2013 at 13:58
  • Are you looking for something like modules (modules.sourceforge.net)?
    – mpy
    May 5, 2013 at 14:24
  • Wow, that would be total overkill :) thanks though! Well, in fact I would like a simpler solution than the one I provided below, not a more complicated one… May 5, 2013 at 20:12
  • To update an old question, I'm looking for the same thing. My use case is to use an iTerm profile to launch a particular environment (simply, setting $GOPATH and cding there). Frankly, I'm very surprised this doesn't exist
    – nfirvine
    Jan 22, 2016 at 1:27

2 Answers 2

3

This site tells us that there is a $ZDOTDIR, which makes a very ugly solution possible:

  1. /distdir/my-cmd:

    Use shell-specific ways to replace init files or fail hopelessly.

    case $(basename $SHELL) in
        zsh)  OLD_ZDOTDIR="$ZDOTDIR" ZDOTDIR="/distdir" zsh -i ;;
        bash) bash --init-file "/distdir/.zshrc" -i ;;
        *)    echo "Unrecognized shell $SHELL"; exit 1 ;;
    esac
    
  2. /distdir/.zshrc:

    Named .zshrc, as the names are hardcoded in zsh, but bash can be passed a arbitrarily named file via --init-file. It would also be possible to name this e.g. our_stuff.sh, and create a .zshrc which contains just . ./our_stuff.sh.

    As we don’t actually want to replace the init files, but to append another, we have to painstakingly recreate the builtin sequence of sourcing them.

    # ignore profile, login & logout rc files, as we want no login shells
    case $(basename $SHELL) in
        zsh)
            test -f "$OLD_ZDOTDIR/.zshenv" && . "$OLD_ZDOTDIR/.zshenv"
            test -f "$OLD_ZDOTDIR/.zshrc"  && . "$OLD_ZDOTDIR/.zshrc"
            ;;
        bash)
            test -f ~/.bashrc        && source ~/.bashrc
            test -f /etc/bash.bashrc && source /etc/bash.bashrc
            ;;
    esac
    
    do_our_stuff!
    
    PS1="myenv! $PS1" #tell the user he’s in a modified shell
    
4
  • Part of my confusion as to what your ultimate goal is: why are you sourcing a .zshrc file when you are starting an instance of bash?
    – chepner
    May 4, 2013 at 17:22
  • 1
    To answer the last question, a login bash shell (interactive or not) always executes /etc/profile if it exists. I think that is the only global startup file for bash (something like /etc/bashrc may be provided by your OS distribution and sourced from a provided default .bashrc or /etc/profile, but bash itself does not look for it).
    – chepner
    May 4, 2013 at 17:25
  • @chepner: I already answered your comment in the question at the beginning of the explanation for the .zshrc file. I want the same file to be sourced in bash, if the user uses bash, and in zsh if he uses zsh. Bash accepts an --init-file, zsh just a $ZDOTDIR, in which it searches for specific, hard-coded filenames. So I gave the file one of those hard-coded names, because bash doesn’t care how it’s named. Got it? :) May 5, 2013 at 14:02
  • About the last question: Thanks! I’ll update the answer accordingly. May 5, 2013 at 14:04
1

Unfortunately, this feature is still absent in zsh, but there's zshi, a small script that achieves what you want. Quoting its README:

Usage: zshi <init-file> [zsh-flag]...

The same as plain zsh [zsh-flag]... except that an additional <init-file> gets sourced after all standard Zsh startup files.

You must log in to answer this question.

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