The main difference with shell config files is that some are only read by "login" shells (eg. when you login from another host, or login at the text console of a local unix machine). these are the ones called, say, .login or .profile or .zlogin (depending on which shell you're using).
Then you have config files that are read by "interactive" shells (as in, ones connected to a terminal (or pseudo-terminal in the case of, say, a terminal emulator running under a windowing system). these are the ones with names like .bashrc, .tcshrc, .zshrc, etc.
bash complicates this in that .bashrc is only read by a shell that's both interactive and non-login, so you'll find most people end up telling their .bash_profile to also read .bashrc with something like
[[ -r ~/.bashrc ]] && . ~/.bashrc
Other shells behave differently - eg with zsh, .zshrc is always read for an interactive shell, whether it's a login one or not.
The manual page for bash explains the circumstances under which each file is read. Yes, behaviour is generally consistent between machines.
.profile is simply the login script filename originally used by /bin/sh. bash, being generally backwards-compatible with /bin/sh, will read .profile if one exists.
The main difference with shell config files is that some are only read by "login" shells (eg. when you login from another host, or login at the text console of a local unix machine). these are the ones called, say, .login or .profile or .zlogin (depending on which shell you're using).
Then you have config files that are read by "interactive" shells (as in, ones connected to a terminal (or pseudo-terminal in the case of, say, a terminal emulator running under a windowing system). these are the ones with names like .bashrc, .tcshrc, .zshrc, etc.
bash complicates this in that .bashrc is only read by a shell that's both interactive and non-login, so you'll find most people end up telling their .bash_profile to also read .bashrc with something like
[[ -r ~/.bashrc ]] && . ~/.bashrc
Other shells behave differently - eg with zsh, .zshrc is always read for an interactive shell, whether it's a login one or not.
The manual page for bash explains the circumstances under which each file is read. Yes, behaviour is generally consistent between machines.
.profile is simply the login script filename originally used by /bin/sh. bash, being generally backwards-compatible with /bin/sh, will read .profile if one exists.
That's simple. It's explained in man bash:
/bin/bash
The bash executable
/etc/profile
The systemwide initialization file, executed for login shells
~/.bash_profile
The personal initialization file, executed for login shells
~/.bashrc
The individual per-interactive-shell startup file
~/.bash_logout
The individual login shell cleanup file, executed when a login shell exits
~/.inputrc
Individual readline initialization file
Login shells are the ones that are read one you login (so, they are not executed when merely starting up xterm, for example). There are other ways to login. For example using an X display manager. Those have other ways to read and export environment variables at login time.
Also read the INVOCATION chapter in the manual. It says "The following paragraphs describe how bash executes its startup files.", i think that's a spot-on :) It explains what an "interactive" shell is too.
Bash does not know about .environment. I suspect that's a file of your distribution, to set environment variables independent of the shell that you drive.
terminal - What is the difference between .bash_profile and .bashrc? - Ask Different
bash_profile or bashrc??
login - Why have both .bash_profile and .bashrc? - Unix & Linux Stack Exchange
bash_profile or bashrc?? : linux4noobs
Videos
.bash_profile is executed for login shells, while .bashrc is executed for interactive non-login shells.
When you login (type username and password) via console, either sitting at the machine, or remotely via ssh: .bash_profile is executed to configure your shell before the initial command prompt.
But, if you’ve already logged into your machine and open a new terminal window (xterm) then .bashrc is executed before the window command prompt. .bashrc is also run when you start a new bash instance by typing /bin/bash in a terminal.
On OS X, Terminal by default runs a login shell every time, so this is a little different to most other systems, but you can configure that in the preferences.
X11 will look at your .bashrc while a "regular" Terminal will look at .bash_profile
However, if you add the following to your .bash_profile, you can then move everything into your .bashrc file so as to consolidate everything into one place instead of two:
if [ -f $HOME/.bashrc ]; then
source $HOME/.bashrc
fi
.bash_profile and .bashrc are specific to bash, whereas .profile is read by many shells in the absence of their own shell-specific config files. (.profile was used by the original Bourne shell.) .bash_profile or .profile is read by login shells, along with .bashrc; subshells read only .bashrc. (Between job control and modern windowing systems, .bashrc by itself doesn't get used much. If you use screen or tmux, screens/windows usually run subshells instead of login shells.)
The idea behind this was that one-time setup was done by .profile (or shell-specific version thereof), and per-shell stuff by .bashrc. For example, you generally only want to load environment variables once per session instead of getting them whacked any time you launch a subshell within a session, whereas you always want your aliases (which aren't propagated automatically like environment variables are).
Other notable shell config files:
/etc/bash_profile (fallback /etc/profile) is read before the user's .profile for system-wide configuration, and likewise /etc/bashrc in subshells (no fallback for this one). Many systems including Ubuntu also use an /etc/profile.d directory containing shell scriptlets, which are . (source)-ed from /etc/profile; the fragments here are per-shell, with *.sh applying to all Bourne/POSIX compatible shells and other extensions applying to that particular shell.
.profile
.profile is for things that are not specifically related to Bash, like environment variables PATH and friends, and should be available anytime.
For example, .profile should also be loaded when starting a graphical desktop session.
.bashrc
.bashrc is for the configuration of the interactive Bash usage, like Bash aliases, setting your favorite editor, setting the Bash prompt, etc.
.bash_profile
.bash_profile is for making sure that both the things in .profile and .bashrc are loaded for login shells.
For example, .bash_profile could be something simple like
. ~/.profile
. ~/.bashrc
If you were to omit .bashrc, only .profile would be loaded.
TL;DR:
~/.bash_profileshould be super-simple and just load.profileand.bashrc(in that order)~/.profilehas the stuff NOT specifically related to bash, such as environment variables (PATHand friends)~/.bashrchas anything you'd want at an interactive command line. Command prompt,EDITORvariable, bash aliases for my use
A few other notes:
Anything that should be available to graphical applications OR to sh (or bash invoked as
sh) MUST be in~/.profile~/.bashrcmust not output anythingAnything that should be available only to login shells should go in
~/.profileEnsure that
~/.bash_logindoes not exist.
Over the last few years, I've had a lot of time to waste, so I have researched this for a bit more than just 10 minutes. I have no idea if this is the best layout, it's just one that happens to work correctly in pretty much all cases.
The requirements:
~/.profilemust be compatible with any /bin/sh – this includes bash, dash, ksh, whatever else a distro might choose to use.Environment variables must be put in a file that is read by both console logins (i.e. a 'login' shell) and graphical logins (i.e. display managers like GDM, LightDM, or LXDM).
There is very little point in having both
~/.profileand~/.bash_profile. If the latter is missing, bash will happily use the former, and any bash-specific lines can be guarded with a check for$BASHor$BASH_VERSION.The separation between
*profileand*rcis that the former is used for 'login' shells, and the latter every time you open a terminal window. However, bash in 'login' mode doesn't source~/.bashrc, therefore~/.profileneeds to do it manually.
The simplest configuration would be:
Have a
~/.profilethat sets all environment variables (except bash-specific ones), perhaps prints a line or two, then sources~/.bashrcif being run by bash, sticking to sh-compatible syntax otherwise.export TZ="Europe/Paris" export EDITOR="vim" if [ "$BASH" ]; then . ~/.bashrc fi uptimeHave a
~/.bashrcthat performs any shell-specific setup, guarded with a check for interactive mode to avoid breaking things likesftpon Debian (where bash is compiled with the option to load~/.bashrceven for non-interactive shells):[[ $- == *i* ]] || return 0 PS1='\h \w \$ ' start() { sudo service "$1" start; }
However, there's also the problem that certain non-interactive commands (e.g. ssh <host> ls) skip ~/.profile, but environment variables would be very useful to them.
Certain distributions (e.g. Debian) compile their bash with the option to source
~/.bashrcfor such non-interactive logins. In this case, I've found it useful to move all environment variables (theexport ...lines) to a separate file,~/.environ, and to source it from both.profileand.bashrc, with a guard to avoid doing it twice:if ! [ "$PREFIX" ]; then # or $EDITOR, or $TZ, or ... . ~/.environ # generally any variable that .environ itself would set fiUnfortunately, for other distributions (e.g. Arch), I haven't found a very good solution. One possibility is to use the (enabled by default) pam_env PAM module, by putting the following in
~/.pam_environment:BASH_ENV=./.environ # not a typo; it needs to be a path, but ~ won't work
Then, of course, updating
~/.environtounset BASH_ENV.
Conclusion? Shells are a pain. Environment variables are a pain. Distribution-specific compile-time options are an immense pain in the ass.
What is the difference between bash_profile and bashrc environment variables?
It helps to understand which files get sourced, when, and why.
.profileis sourced by a login shell on startup. Typically, the only login shell you start is the one started when you log in, but you can run a login shell at any time withbash -l. (Also, on macOS, there is no initial login shell, so terminal emulators tend to run a login shell for each new window.).profileis an ideal place to set environment variables that can be inherited by any program started from the login shell..bashrc, on the other hand, is sourced by non-login interactive shells, such as those started by terminal windows (most configs also source.bashrcin interactive login shells though). This is where you set things specific to your interactive shell that aren't otherwise inherited from the parent process. For example,PS1is set here because only interactive shells care about its value, and any interactive shell will source.bashrcanyway, so there is no need to define and exportPS1from.profile.And though you didn't ask, it's worth pointing out the difference between
.profileand.bash_profilehere..profileis "shared" by all POSIX shells (such asdash), so don't put anythingbash-specific here..bash_profile, though, is only used bybash, so you can usebashextensions in it. If.bash_profileis present,.profilewill be ignored, so if for whatever reason you want to use both, you can add. ~/.profileto the top of your.bash_profile.
~/.profile is only called when you first log into your account. Any changes you make after that it would be wise to log out and back in so settings take effect. ~/.bashrc is called every time you launch a terminal window. There is another profile file and it is in the /etc/ directory. The main difference between the two is that the /etc/profile is called when anyone logs into the system, and the ~/.profile is called when only the user logs in.
If your export lines are only used in a terminal session then I would add them to the ~/.bashrc file as they are only valid during the terminal (bash) session. But, if you want them to be there with or without a terminal open, add them to the ~/.profile file, but like @chepner has stated do not put bash specific commands in the ~/.profile file.
If you screw up these files, there are default files stored in the /etc/skel/ directory that you can copy back over to your home directory. Also, the /etc/skel/ files are also used when you boot to a LiveUSB/CD/DVD, so if you modify those on your live media and then when it completes the boot you can have your own variables set.