45

i'd like to start zsh similar to

zsh -c 'my_prog option1 option2'

but instead of exiting after running that command, leaving me at the propt of the invoked zsh (not wherever it is being called from). one particular use-case for this is in screenrc files, you could do something like:

screen -t my_prog 0 zsh -c 'my_prog opt1 opt2'

and after running that command you're left with a shell there instead of it closing.

32

Not that I would advise doing this.

(sirius)~: zsh -c 'print hello; zsh -i'
hello
(sirius)~: echo $SHLVL
2

There are other tricks you can play with screen and using the $STY variable.

If you want something run from zsh with individual screens, you can check the $STY variable within your .zshrc or .zlogin. It is in the format <PID>.<TTY>.<HOSTNAME>.

if [[ -n $STY ]] then
  if [[ -f ~/.zsh-$STY[(ws:.:)2] ]] then
    . ~/.zsh-$STY[(ws:.:)2]
  fi
fi

If in screen, and if ~/.zsh-<TTY> (from the $STY variable) exists, source that, then continue on your merry way. You can also set an environment variable before calling the interactive shell.

> FOO=bar zsh -i
> env | grep FOO
FOO=bar

> RUNTHISCOMMAND=/path/to/script zsh -i
.zshrc:
if [[ -n $RUNTHISCOMMAND ]] then
   $RUNTHISCOMMAND
fi

Add those checks into your .zshrc/.zlogin.

2
  • 1
    kudos for teaching me about SHLVL – Nicolas Dumazet Jan 6 '10 at 5:00
  • i was hoping to avoid the nested shell, but oh well. – Autoplectic Jan 6 '10 at 9:24
15

I found a solution that works without an extra shell here. Add:

if [[ $1 == eval ]]
then
    "$@"
set --
fi

to .zshrc, then call zsh with

zsh -is eval 'your shell command here'

Really great for starting up lots of shells at once.

1
  • It should be noted that this is best placed at the very end of the .zshrc. I had some plugins that had automatically placed their setup code in .zshrc after the eval hook. Typically I'm running infinite processes like npm start in the eval hook. When killing them with CTRL + C I was always surprised that some zsh plugins had stopped working. Of course the reason is that the .zshrc only got evaluated up to the $@. – bluenote10 Mar 6 at 9:00
8

I have eval "$RUN" at the end of my .zshrc. I can now run commands without the extra shell, with:

RUN='my_prog opt1 opt2' zsh
1
  • This seems a weird kludge - but it works so well! – zaTricky Feb 28 '17 at 5:32
7

What about appending ; exec zsh to the command? That way there's only one shell left at the end.

1
  • 6
    You actually don't need the exec if you ; zsh -i, it does that for you already. – Darren Hall Jan 6 '10 at 17:47
0

I have this in my .zshrc:

alias uce='USE_CUSTOM_ENV=1 zsh'
if [[ "${USE_CUSTOM_ENV}" == "1" ]]; then
        alias a='stuff I need in this context'
        alias x='exit'
        ...

        PROMPT="${PROMPT}%{$terminfo[bold]$fg[red]%}[CUSTOM_ENV] %{$reset_color%}"
        my_prog option1 option2
fi

Upon invoking uce on the command line a new interactive subshell is invoked where my_prog is executed. This approach has the advantage of giving me a custom environment (with aliases, functions, envvars, etc.) for the specific context.

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.