Shells bash, csh, tcsh, zsh
The shell is the program that acts as a user interface to send commands to the kernel. The kernel then interprets the command and tells the CPU and other computer hardware how to carry out the particular task.
Every time a user logs in, a shell is started. The type of shell is up to the user, but most often the default is set to bash
.
bash
The Bourne Again Shell
shell includes the basic features common to all unix shells, including pipelining, here documents, command substitution, variables, control structures and wildcards. It is the most common default shell for user accounts.
csh
The C Shell
was created by Bill Joy at the University of California, Berkeley. His main intent was to create a shell with C language-like syntax. Thus, it included things like control structures and expression grammar.
Other features included history and editing mechanisms, aliases, directory stacks, tilde notation, cdpath, job control and path hashing.
tcsh
The tcsh
was developed to be compatible with the C shell.
The t in tcsh
comes from TENEX, which was an operating system.
tcsh
is very close to csh
with extensions like command-line completion, command-line editing and other features. Mac OS X's used to come with tcsh
as default, but switched to bash in Version 10.3.
zsh
The Z shell
was designed for interactive use.
Some of the features of z shell include spell check, editing of multi-line commands in a single buffer, improved variable and array handling, customization, programmable command-line completion and themeable prompts.
And many, many more!
As you can see, there are plenty of shells to choose from! As you get to know more about the terminal and shell, you may want to upgrade to another shell. For now, however, bash will suit our needs just fine.
Acclimating to our Environment printenv, set
Our environment is the area that the shell builds every time a new session is started. Programs are able to access our environment variables to their tailor functions according to a user's settings.
For example, a program can access where your TEMP folder is through the environment variable TMPDIR.
There are two types of variables stored - environment and shell. Let's discuss the environment variables first.
Environment Variables
Environment variables are the variables that define the current shell session, and any child shells or processes that spawn from it.
We can see the environment variables with the printenv
command.
$ printenv
TERM_PROGRAM=iTerm.app
SHELL=/bin/bash
TERM=xterm-256color
USER=JohnDoe
MAIL=/var/mail/JohnDoe
PATH=/usr/local/bin:/usr/bin:/bin
PWD=/home/JohnDoe
LANG=en_US.UTF-8
SHLVL=1
HOME=/home/JohnDoe
LOGNAME=JohnDoe
LESSOPEN=| /usr/bin/lesspipe %s
LESSCLOSE=/usr/bin/lesspipe %s %s
_=/usr/bin/printenv
You'll find quite a few variables. You can also list just one variable by typing the variable name as an argument to printenv
.
$ printenv USER
JohnDoe
Here's just some of the most common environment variables.
- DISPLAY
- Name of your current display.
- EDITOR
- Name of program to be used for text editing.
- SHELL
- Name of shell program (bash by default).
- HOME
- Path to user's home directory.
- LANG
- The character set and collation order of your language.
- Where a user's mail is found.
- OLD_PWD
- Previous working directory (same as
cd -
). - PAGER
- Name of the program to be used for paging output.
- PATH
- Colon-separated list of directories where the shell searches before executing a command.
- PS1
- Prompt string 1, or how your shell prompt should appear.
- In our case, we have a simple
$
- PWD
- Current working directory path.
- TEMP
- Where a user can store temporary files.
- TERM
- Type of computer terminal being used.
- TERM_PROGRAM
- Type of program used as a terminal.
- TZ
- Time zone.
- USER
- Current logged in user.
- _
- Most recently executed command.
env - printenv's sibling command
In addition to the printenv
command is env
.
These two commands are very similar, except printenv
can request values of individual variables, while env
lets you pass variables through to a command.
The env
variable is useful when you want to create child processes with an alternate variable. The -c
option here allows you to pass in a command as a string.
$ env VAR="HelloWorld" bash -c 'command'
Shell Variables
Shell variables are useful for keeping values in scripts, and control the way the shell behaves. To see the shell variables use the set
command. This displays the shell variables, environmental variables, local variables and shell functions.
$ set
...
DIRSTACK=()
EUID=501
GROUPS=()
HISTFILE=/Users/shawnPC/.bash_history
HISTFILESIZE=500
HISTSIZE=500
HOME=/Users/shawnPC
HOSTNAME=Shawns-Mac-Pro
HOSTTYPE=x86_64
IFS=$' \t\n'
ITERM_PROFILE=Default
ITERM_SESSION_ID=w0t0p0
...
Since this will have many more variables, consider piping the listing to the less
command.
Here are some common shell variables:
- BASHOPTS
- List of options when bash was executed.
- BASH_VERSION
- Version of the bash in use.
- COLUMNS
- Number of columns that are being used to draw output on screen.
- DIRSTACK
- Stack of directories available with pushd an popd commands.
- HISTSIZE
- Number of lines of command history allowed in memory.
- PS2
- How the secondary prompt should appear (commands spanning multiple lines).
- UID
- User id of current user.
Bash startup files .bash_profile, .bashrc
When the bash
starts up, it reads configuration files to set up the environment. These files are known as startup files.
Startup files work by first loading the default environment shared by all users. Then it loads files in the user's home directory to give a more tailored experience per user.
Two types of shell logins
There are two types of shell logins: login and non-login shell sessions. Depending on which one you choose to boot your shell, a different group of startup files are executed.
Login shell sessions
For a login shell session, a username and password in necessary.
Here is the order in which the startup files are executed in a login shell.
- /etc/profile
- Global configuration file that loads for all users.
- Automatically read into shell if login shell.
- /etc/bashrc
- Global configuration file that loads for all users.
- ~/.bash_profile
- The user's personal startup file.
- Oftentimes the .bash_profile file contains code that executes the .bashrc file.
- ~/.bash_login
- This file is executed if a user's .bash_profile is missing.
- ~/.profile
- A fallback file if the above two are not found.
- ~/.bash_logout
- Executed when a user logs out.
Non-login shell sessions
Non-login shells inherit the environment from their parent process.
- /etc/bash.bashrc
- Configuration file for all users.
- ~/.bashrc
- Startup file.
The main difference in files being executed is that login shells run .bash_profile on startup, while non-login shells run .bashrc. However, .bashrc is usually executed from .bash_profile.
Hidden files
Remember that the . before a file name means that it is hidden. To view hidden files, use ls -a
.
Configuring our environment
There is a convention of where to store certain variables when configuring your environment.
If you want to add any directories to your $PATH
, you should do it in your ~/.bash_profile. For all others (configuring aliases or setting umask), place it in ~/.bashrc.
In the next section, let's talk about how to properly set environment variables so that your settings are loaded upon every login.
Setting Shell and Environment Variables set, export, source, .
Now let's learn how to properly set a shell or environment variable.
Setting shell variables
Shell variables, by convention, should be kept in all caps.
To set a shell variable, simply set it equal to a value.
$ VARIABLE='value'
It's the little things that matter most
Make sure to not use any spaces between the equals sign. If we do, then the shell will interpret the VARIABLE
as a command, and the =
as an argument.
Additionally, be sure to use single quotes to prevent expansions.
$ VARIABLE = 'value'
-bash: VARIABLE: command not found
Great! Now let's see if it was successfully set with the set
variable, which lists out all shell, environmental, and local variables.
$ set | grep VARIABLE
VARIABLE=value
This will list out all variables, and find any matching variables with VARIABLE in their name.
Additionally, we can check that it's a shell variable and not an environment variable by making sure it's not an output with the printenv
command, which only prints out environmental variables.
Setting Environmental Varibles
To set environmental variables, we use the export
command.
$ export TEST_VAR='testing'
$ printenv | grep TEST_VAR
TEST_VAR=testing
Note that any child processes will inherit the environment variables we set.
Changing to an environment variable from a shell variable
To change an environmental variable to a shell variable, use the -n
option.
$ export -n TEST_VAR
$ printenv | grep TEST_VAR
# No output since TESTVAR is no longer an environment variable.
$ set | grep TEST_VAR
TEST_VAR='testing'
Unsetting a variable
To completely unset a variable (or remove it from the session) use the unset
command.
$ unset TEST_VAR
Example: adding to the $PATH
Remember that the $PATH
variable contains a colon-separated list where the shell looks for any executable commands.
To add to our $PATH
and have it persist for future sessions, we edit our ~/.bash_profile file, appending a colon then file name at the end.
PATH=$PATH:/path/to/new/file
export PATH
Remember to not include spaces!
Now that our new $PATH
variable in set in our .bash_profile, we have to run the file.
Executing a startup file
To execute either startup file, use the source
command. Or you may use its shortcut, which is just a period (.
).
$ source ~/.bashrc
$ . ~/.bashrc
Conventions for storing variables
Remember, any modifications to the path variable should be placed in the .bash_profile file.
For all other changes, edit .bashrc.
If you're a system admin and need to make changes to everyone, go ahead to edit /etc/profile.
Customizing our Command Prompt $PS1
Ever notice the $
in front of every command in this tutorial series? Surely, the text that appears before your command input is different. Here, we'll show you how to customize this by changing the $PS1
variable.
The $PS1 Variable
The variable that stores the configuration is $PS1
(short for Prompt Statement).
To check your own $PS1
, use the echo
command.
$ echo $PS1
\n\[\033[1;34m\]\W$\[\033[0m\]
On my personal computer, I use this setting. It outputs the current working directory, then a $
symbol, all in blue text. It then sets the user's font color to default.
Characters used for customization
Here are a list of characters that act as variables that you can use for your prompt statement. They are all preceded by the escape key (\
).
- \a
- ASCII bell character (beep).
- \d
- Current date eg. Wed May 25.
- \e
- ASCII escape character.
- \h
- Hostname of local machine, minus the domain name.
- \H
- Full hostname.
- \j
- Total number of jobs managed by the shell session.
- \l
- The name of current terminal device.
- \n
- Newline character.
- \r
- Carriage return.
- \s
- Name of shell program
- \t
- Current time in 24-hour HH:MM:SS.
- \T
- Current time in 12-hour HH:MM:SS.
- \@
- Current time in 12 hour am/pm format.
- \A
- Current time in 24 hour HH:MM format.
- \u
- Username of current user.
- \v
- Version number of shell.
- \V
- Version and release numbers of shell.
- \w
- Current working directory.
- \W
- Last part of current working directory name.
- \!
- History number of current command.
- \#
- Number of commands in this shell session.
- \$
- Displays a $ symbol for regular uses, # for root.
- \[
- Signals start of a series for non-printing characters. They are used to manipulate the editor in colors or something else.
- \]
- Close series.
Let's try building our own!
Let's say we want current time (\@
), the current working folder (\w
), followed by a greater than symbol (>
).
Remember to use single quotes to prevent shell expansion!
$ export 'PS1=\@ \w >'
05:01 PM ~/snipcademy/code >
It looks great! Although it would look even better with some color.
Adding color
To add color, we must make use of the ANSI escape code, \e. This tells the terminal not to interpret the sequence, but to interpret it as a command.
Here are the values that we may use for text font decoration.
- 0
- Default.
- 1
- Lighter corresponding color.
- 4
- Underline.
- 5
- Blinking.
- 7
- Inverse.
Since this is a sequence of non-printing characters, we enclose them in \[
and \]
characters.
Here is a list of colors you can choose from:
- [0;30m
- Black
- [0;31m
- Red
- [0;32m
- Green
- [0;33m
- Brown
- [0;34m
- Blue
- [0;35m
- Purple
- [0;36m
- Cyan
- [0;37m
- Light Gray
- [1;30m
- Dark Gray
- [1;31m
- Orange
- [1;32m
- Light Green
- [1;33m
- Yellow
- [1;34m
- Light Blue
- [1;35m
- Light Purple
- [1;36m
- Light Cyan
- [1;37m
- White
$ export PS1='\[\e[0;36m\]\@ \w >'
To specify the color that the user types, we add another color to the end of our PS1
.
$ export PS1='\[\e[0;36m\]\@ \w >\[\e[1;37m\]'
06:32 PM ~/snipcademy >
Adding text background color
To add a text background color, use a similar method but with these sequences.
- \e[0;40m
- Black
- \e[0;41m
- Red
- \e[0;42m
- Green
- \e[0;43m
- Brown
- \e[0;44m
- Blue
- \e[0;45m
- Purple
- \e[0;46m
- Cyan
- \e[0;47m
- Light Gray
$ export PS1='\[\e[0;36m\]\@ \w >\[\e[1;37m\] \[\e[0;44m\]'
06:32 PM ~/snipcademy > User input text here.
Custom cursor positioning
You may also customize your settings so that you can move the cursor line around.
- \e[l;cH
- Move to line l, column c.
- \e[nA
- Move cursor up n lines.
- \e[nB
- Move cursor down n lines.
- \e[nC
- Move forward n characters.
- \e[nD
- Move cursor backward n character.
- \e[2J
- Clear screen and move cursor to upper-left corner.
- \e[K
- Clear from cursor position to end of current line.
- \e[s
- Store current cursor position.
- \e[u
- Recall stored cursor position.
Persisting your customized prompt
To save your prompt, place it in your .bashrc file.