If I am typing in a terminal and do this
% bash
% [enter many commands in this shell]
% bash
% [enter many commands in this shell]
. . .
(could be zsh
instead of bash
) and I forget how many shells deep I am and want to get back to the top-level shell, how do I do it without accidentally closing my terminal?
The dangerous thing I try to do is
% exit
% exit
% exit
and if I enter one more exit
than I need, I unintentionally close my terminal, possibly losing work. It can ruin a day.
Answers that aren't good enough:
I know I could scroll up or do a search in the terminal for the commands, but that's painful and isn't always possible. I know I could avoid this situation in the future with tricks in my environment or by just never creating new shells like that, but that doesn't answer the question. If I'm lucky, my command prompt changes, so I know I'm at the top when the prompt changes back, assuming I notice. But, let's say it doesn't change. Note that entering history
at the command line doesn't help because the history of the previous shell typically doesn't carry over. Entering return
doesn't help.
If my computer (a Mac) keeps history for all shells somewhere, that sounds like a potential guaranteed solution, but is that typical? It also still sounds painful to sift through. I'm hoping for a better answer, like a simple command that uses ps
to show me my stack of nested shells in the current terminal. Keep in mind that I might have many terminal windows.
[Inspired by Gairfowl's comments] You could add something like this to your .bashrc and .zshrc:
unshell() {
case "$0" in
-*) echo "Already at top-level shell" >&2 ;;
*sh*)
parent="$(ps -ocomm= -p$(ps -p$$ -oppid=))"
case "$parent" in
-*) echo "Exiting to top" >&2 ;;
*sh* ) echo "Not at top yet" >&2 ;;
* ) echo "Not sure what the parent process ($parent) is." >&2 ;;
esac
exit ;;
* ) echo "\$0 is weird ($0); not sure what to do." >&2 ;;
esac
}
You'll still have to run it multiple times to exit out of multiple levels of shells, but it won't exit from the top level, and will let you know when you've exited the last sub-level shell.