Is there an Unix convention for setting personal environment variables? I read they should be put in $HOME/.bash_profile instead of $HOME/.bashrc. Nonetheless, I was thinking of providing a way to distinguish my own variables. This way even though I would forget one I could tell at first glance whether it has been set by me or not. For instance when I do the autocompletion in the terminal I could make my variables start with an underscore, or a minus 'm' as in one of C++ language's conventions. I understand there might not be an absolute answer but I'd like to hear about some good practice and conventions that work toward this purpose: providing a simple way to distinguish system environment variables from personal ones.

  • Put them in your $HOME/.bash_profile, and they are yours since are put in your profile. .bash_profile is executed for login shells, while .bashrc is executed for interactive non-login shells. – FarazX Aug 12 '16 at 14:55

Where to set environment variables is covered in What's the best distro/shell-agnostic way to set environment variables?

Regarding naming, the main reason to set environment variables is because an application uses them, so you don't get to choose the name.

There is no concept of namespaces for environment variables. The closest thing is to pick a prefix, generally of the form SOMETHING_ (i.e. the prefix ends with an underscore and you have variables SOMETHING_FOO, SOMETHING_BAR, …). But most variables aren't for a specific application, but rather a family of applications. If a variable is only meaningful in one application, it should generally be a command line option. So there isn't much need for namespaces.

If you're defining variables only for use on the command line, then don't use environment variables, use shell variables. (See Difference between environment variables and exported environment variables in bash) If you define a variable in a shell script and you don't use export, that's a shell variable, not an environment variable, and it's only visible in the shell where you defined them. So if you're defining a variable for use on the command line:

  • Define it in your shell interactive startup file (~/.bashrc for bash, ~/.zshrc for zsh, ~/.config/fish/config.fish for fish).
  • Don't export it.
  • There's a widespread convention that environment variables are all-uppercase and shell variables are all-lowercase.

For your own use, pick whatever names you like, as long as they don't conflict with environment variables that you use (environment variables are automatically imported as shell variables). I don't recommend an initial underscore because that's what bash and zsh's completion systems use internally.


Here are my recommendations for where to set the environment, along with explanations.

The relevant details are:

  • The user profile file is ~/.bash_profile, ~/.bash_login, or ~/.profile. I suggest using one of the first two, because the last one overlaps with other shells. However, see Note on GUI login at the end.

  • The user rc file is ~/.bashrc.

  • An interactive login shell (e.g. a console login, or ssh login) reads the profile file only.

  • A noninteractive login shell is rare, but it might occur run during GUI login. Either way, if this is a Bash shell, it acts as a noninteractive login shell, and reads the profile file only.

  • An interactive nonlogin shell (e.g. new tab in XTerm/Konsole) reads the rc file.

  • A noninteractive nonlogin shell (e.g. shell script) reads neither, with one important exception: If started by ssh, it reads the rc file.

The exception involving ssh is motivated by the fact that when a script is run through ssh (ssh $host my_remote_script), the environment (mainly PATH) is not already set up, as is the case when running a local script. Thus, IMO, the exception is a motivation to set the environment in ~/.bashrc, so that the same environment is used for both locally-invoked and remotely-invoked scripts.

Based on all this, my recommendations are:

  • Profile file:

    • Do not set anything that might be useful to a remotely-invoked script, including PATH.
    • Source the rc file unconditionally: . ~/.bashrc.
  • Rc file:

    • Set environment variables as needed.
    • Beware that the file will be sourced when the environment is already set (by interactive nonlogin shells). So, if you unconditionally do PATH=$HOME/bin:$PATH, you might end up with PATH=$HOME/bin:$HOME/bin:... after sourcing it twice (an annoyance, not an error). An easy fix is to guard the environment setting:

      # ~/.bashrc
      if [ ! "${MY_ENV_SET:-}" ]; then
          export MY_ENV_SET=1
    • Only define shell niceties for interactive shells:

      [ "$PS1" ] || return 0
      source ~/.bash_alias
      eval $(dircolors -b ~/.dircolors)
      source /etc/bash_completion

GUI login. One last important thing you need to consider is how your GUI sets PATH during startup. This might be done using Bash, or not. In my case, I use KDE, and this file is sourced during startup:

# ~/.kde/env/path.sh
# https://userbase.kde.org/Session_Environment_Variables
PATH=$(env -i /bin/bash -lc 'echo $PATH')

This invokes a (rare) noninteractive login Bash shell, using an empty environment, which also sources the rc file, and all is consistent.

If you are using another GUI (Gnome?), you should look into how PATH is set during its startup. If your GUI sources ~/.profile, make sure to source the rc file from there as well.

  • Your facts are mostly correct but your advice is almost consistently bad. See unix.stackexchange.com/q/88201 and unix.stackexchange.com/a/3085 . ~/.bash_profile is not read by most GUI logins whereas ~/.profile is, so .profile is preferable. ~/.bashrc is only read by interactive shell so it should never set environment variables, otherwise they are not set by programs that aren't started from a terminal. The profile file should not source .bashrc unconditionally, only if the shell is interactive. – Gilles Aug 13 '16 at 23:01
  • In any case this, you aren't answering the question, which is not where to set environment variables but how to name them. – Gilles Aug 13 '16 at 23:02
  • I addressed the GUI login issue. – Matei David Aug 14 '16 at 0:23
  • Other than that, instead of distastefully dismissing advice (by shamefully calling it "consistently bad") and appealing to the logical fallacy that is an argument of authority, I challenge you to take time and explain what you find "consistently bad", or else retract such comments. Thanks! – Matei David Aug 14 '16 at 0:29
  • To address your remaining argument, apart from the GUI startup issue- Any program not started from the terminal will (a) have the environment already set by the GUI, and (b) if for some peculiar reason they don't, and they need to source ~/.profile, sourcing the rc from there covers that case. In your last sentence, "should not" is probably a personal preference. I am not saying your scheme doesn't work, I am only challenging your assertion that mine is "consistently bad" or even just "bad". IMO, these are different ways of setting things up. – Matei David Aug 14 '16 at 0:55

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.