0

In bash, we have the inherent separation of .bash_profile and .bashrc, with the former running for login shells and the other for all shells. Now, I understand it's common to start an interactive non-login shell from a non-shell process, and for this reason I find myself running quite a bit of initialization stuff in my .bashrc. The thing is, one also often invokes the shell from within an interactive shell session, or within shell scripts; and I'm not at all sure none of them runs .bashrc. So, I think I would like to somehow constrain some of the stuff I do in my .bashrc to only happen in "top-level" interactive shells in some sense.

Is there some convention on how this is done? Or perhaps, is it too much of a hassle compared to the benefit?

4
  • Subshells don't run .bashrc. They don't really need to, since they're already copies of the main shell which already did run whatever initialization files it did in the mode it was in. That should be easy to check by putting something like echo this is bashrc in .bashrc and running e.g. (echo hi) or : $(echo hi).
    – ilkkachu
    Commented Dec 9, 2021 at 9:54
  • I suppose by "subshell" he means new bash process...(for the record, when run as sh, --norc is implied...)
    – Tom Yan
    Commented Dec 9, 2021 at 9:58
  • @TomYan, perhaps. And the possible misuse of the word is why I didn't write that as an answer. But the question doesn't show what they mean.
    – ilkkachu
    Commented Dec 9, 2021 at 10:12
  • 1
    Please edit your question and explain what you mean by subshell. Neither subshells nor shell scripts read bashrc normally so this is all a bit unclear. Can you maybe add some specific examples?
    – terdon
    Commented Dec 9, 2021 at 17:49

2 Answers 2

2

It seems like what you want to do is to avoid .bashrc from being (fully) sourced again if the new bash process is spawned from one that already did, regardless of whether it's interactive or not.

You can do something like this:

Hello, I am a "first" shell
$ cat .bashrc
[ -n "$SPAWNING" ] && return

export SPAWNING=yes

echo 'Hello, I am a "first" shell'
$ bash
$
exit
$ env -i bash
Hello, I am a "first" shell
$ exit
$

As I've shown though, there's still the caveat that it won't help when the new bash is spawned with all the env var cleared.

1
  • That sounds reasonable. And - if someone clears the environment than it's their responsibility anyway.
    – einpoklum
    Commented Dec 10, 2021 at 8:03
1

The "$-" variable contains the options for the current shell at its invocation; you might find "i" present, which would indicate an interactive shell.

case "$-" in
*i*) echo in interactive shell
     # do interactive-only setup here
     ;;
esac
4
  • though AFAIK bashrc is only read by interactive shells, and if it's sourced from the "profile" files for login shells, it's often guarded by the check on $- or $PS1 anyway. (PS1 also being unset in non-interactive shells.)
    – ilkkachu
    Commented Dec 9, 2021 at 20:27
  • I think bash's command-line is such that it reads bashrc and bash_profile unless you tell it not to, regardless of interactivity. Am I wrong? Also, is a shell called from within an interactive shell not interactive itself?
    – einpoklum
    Commented Dec 10, 2021 at 8:05
  • @einpoklum, no, it doesn't always read them, see: gnu.org/software/bash/manual/html_node/…. Though the rules there are somewhat complex, but mainly it reads "profile" for interactive login shells and "bashrc" for interactive non-login shells. Yes, if you run bash from an interactive shell, opening a new shell you can interact with, that's another interactive shell. But it's not a subshell, which is why people keep asking you to edit your question to show what situation you actually mean.
    – ilkkachu
    Commented Dec 10, 2021 at 9:41
  • @ilkkachu: Edited.
    – einpoklum
    Commented Dec 10, 2021 at 9:48

You must log in to answer this question.

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