What is the difference between shell, bash, terminal?

Shell is a command-line interpreter and there are various types of shell like Bourne shell (sh) and C shell (csh). Bash (Bourne-Again shell) is written as part of GNU Project to provide a superset of Bourne Shell functionality.

Terminal used to be a physical hardware device to access a computer system when computer is bulky and expensive. The Terminal app on Mac OS X is called a terminal emulator actually, whose function is to emulate a terminal as its name suggested.

Here is a good answer for more detailed information.

How to set $PATH for bash?

Difference between /etc/profile and /etc/bash.bashrc, ~/.bash_profile, ~/.bash_login, ~/.profile and ~/.etc/.bashrc

Here is some information from the manpage of bash:

When bash is invoked as an interactive login shell, or as a non-interactive shell with the –login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable. The –noprofile option may be used when the shell is started to inhibit this behavior.

When an interactive shell that is not a login shell is started, bash reads and executes commands from /etc/bash.bashrc and ~/.bashrc, if these files exist. This may be inhibited by using the –norc option. The –rcfile file option will force bash to read and execute commands from file instead of /etc/bash.bashrc and ~/.bashrc.

To make my life easier, I put all the bash configurations in ~/.bashrc. And then in ~/.bash_profile I add the following codes to call ~/.bashrc:

1
2
if [ -r ~/.profile ]; then . ~/.profile; fi
case "$-" in *i*) if [ -r ~/.bashrc ]; then . ~/.bashrc; fi;; esac

So if I want to add more values to $PATH I just prepend or append it to the original $PATH, and it will works no matter how the shell starts.

1
export PATH=/usr/local/bin:$PATH

There are two excellent links about Bash startup files loading order:

The path_helper function

Since OS X now uses path_helper to manange the $PATH environment variable, when path_helper is called it looks new paths to add in the following order:

  • reads from /etc/paths
  • files under the folder /etc/path.d/
  • appends the initial value of $PATH (/usr/bin:/bin:/usr/sbin:/sbin)
  • the default contents of file /etc/paths is
1
2
3
4
5
/usr/bin
/bin
/usr/sbin
/sbin
/usr/local/bin

Since I use Homebrew to manage packages on my Mac, I change the order of /usr/local/bin to the first place (this is the only thing I changed under /etc/):

1
2
3
4
5
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin

It is also possible to add new $PATH variables by adding file in the /etc/path.d folder, but I don’t recommend this way. The modifications here is system wide and will work for all users. All the files in this folder is created automatically when I install other software. For example after I installed TeXlive a file named TeX with following cotents is created:

1
/usr/texbin

And after I install Git (not from Homebrew) a file named git with git’s path is created:

1
/usr/local/git/bin

Note: path_helper only appends unique paths so no duplicates here.

I learnd this infomaiton from Manage $PATH on Mac OS X Lion 10.7

How to set $PATH and exec-path for Emacs?

In Emacs the $PATH varialbe is used for eshell, shell, bash running within Emacs. The exec-path is used for emacs to run other programe like aspell or latex. Generally the exec-path is copied from the $PATH varialbe.

Depending on how Emacs is started, the $PATH environment variable may be different in Emacs.

  • If Emacs is started from a shell, it will inherit the $PATH from the shell.

  • If Emacs is started from Application, it will only have the default $PATH.

So in order to keep the $PATH in Emacs similar to those in shell, I have to add some paths manullay in my Emacs configuration file:

1
2
3
;; LaTeX compile
(setenv "PATH" (concat "/usr/texbin:/usr/local/bin:" (getenv "PATH")))
(setq exec-path (append '("/usr/texbin" "/usr/local/bin") exec-path))

How to set other environment variables like $PYTHONPATH, both for a shell and Emacs?

Suppose I installed some custom Python modules by adding their path to $PYTHONPATH in ~/.bashrc file:

1
2
# setting PYTHONPATH
export PYTHONPATH=$PYTHONPATH:$HOME/Projects/Python/Modules:$HOME/Projects/Python/GUI

It works perfect if I start python or ipython in Terminal, but when I try python startd from eshell or Elpy to run python scripts, the custom module is not founded. The reason is the same as the above section: the custom python module path is not added in emacs’s $PATH variable. To fix it add the following lines to Emacs configuration file:

1
2
3
4
5
;; Set PYTHONPATH, because we don't load .bashrc
(setenv "PYTHONPATH"
    (concat
     "/Users/xiaok/Projects/Python/Optics/HWFS:"
     "/Users/xiaok/Projects/Python/GUI:"))