1

Due to constraints at my workplace, the default shell for every user is tcsh, and I am required to use tcsh as my non-interactive shell (i.e. we do most of the environment configuration across projects in tcsh init files). However, I like using zsh as my interactive shell.

In order to inherit the environment from tcsh when I switch to zsh, I usually first start an interactive shell in tcsh and later switch to zsh with exec zsh. This seems to be working well.

However, sometimes we update our tcsh init files, and I need to refresh my environment accordingly from a runningzsh shell. I believe the best way to approach this problem is to switch to tcsh to source its init filts and then switch back to zsh.

In practice I resort to the following

> # Running from a zsh interactive shell. 
> # Various tcsh and zsh init files have been updated
> exec tcsh
> exec zsh
> # I am back to zsh with the updated environment

But I am wondering several things:

  1. Is there a way of collapsing

    > exec tcsh
    > exec zsh
    

    into one command? I have tried with:

    > exec tcsh; zsh
    > exec tcsh; exec zsh
    

    but none of them seem to work. The only one that seems to work is

    > exec tcsh & exec zsh
    

    but I am not sure that is doing what I need.

  2. What other ways are there for fully restarting my interactive shell while re-sourcing my non-interactive environment (i.e. as if I was logging in again in tcsh and then switching to zsh)

  3. More generally, what is the recommended practice for using different shells for interactive and non-interactive work and making sure that the interactive shell starts with the environment from the non-interactive shell? (with the possibility of modifying bits of this environment in the init files of the interactive shell )

2 Answers 2

2

You can collapse your 2 exec commands into a single command as:

exec tcsh -c zsh

You could update the environment in your current zsh process using:

eval $(env -i tcsh -c env)

Using env -i would cause the following command to be run with an empty environment. That runs tcsh to process the startup files. The -c option to tcsh then runs another copy of env, but this time without a command so it just prints the current contents of the environment set by tcsh. Then the eval $(...) causes zsh to parse that output.

In my testing, the use of env -i is necessary to prevent zsh from trying to set environment variables that had been set by itself, including the _ variable which is read only. That attempt caused the eval to fail without processing at least part of the output.

2
  • Thanks @qqx! I would also want to source all my zsh init files after sourcing my tcsh files. How should I proceed for this starting from your answer? Would eval$(env -i tcsh -c env) and then eval$(zsh -c env)? do the work? Mar 13, 2013 at 15:35
  • 1
    That won't work, the sub-zsh would always include the _ variable in the environment. Even if it did work, that would only get changed environment variables it wouldn't pick up any other changes to the zsh startup files such as options, aliases and function definitions. You could source individual files, but you may be better off just using the first portion of my answer; or even exiting your original zsh process and then restarting tcsh and zsh.
    – qqx
    Mar 13, 2013 at 15:52
0

I assume that the non-interactive shell is used for script execution.

The easiest way to express that a script needs a special interpreter is to use the shebang, e.g. as first line of your script:

#!/usr/bin/tcsh
1
  • Thanks. We have shebangs in almost every script. The problem I have is one of properly restarting and inheriting my non-interactive environment when I am working on my interactive shell. Mar 13, 2013 at 15:00

You must log in to answer this question.

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