Last modified: June 06, 2026
This article is written in: 🇺🇸
A Unix shell is a command-line program that lets a user communicate with the operating system. Instead of using buttons and menus, the user types commands, and the shell interprets those commands.
For example, when you type:
ls
the shell understands that you want to list files in the current directory. It then asks the operating system to run the appropriate program and displays the result back to you.
The shell is useful because it gives direct control over the system. You can use it to manage files, run programs, install software, configure your environment, automate repetitive work, and write scripts.
The shell sits between the user and the operating system.
+-------------------+ +----------------+ +--------------------+
| | | | | |
| User Input |<----->| Shell |<----->| Operating System |
| (Keyboard/Screen) | | (e.g., Bash) | | (Kernel/HW) |
| | | | | |
+-------------------+ +----------------+ +--------------------+
The user enters a command through the keyboard. The shell reads the command, interprets it, and passes the request to the operating system. The operating system then interacts with hardware and system resources to complete the task.
A simple example is:
mkdir projects
This command asks the system to create a directory named projects.
The shell does not usually do all the work itself. Instead, it starts programs, passes arguments to them, manages input and output, and gives the user a way to control the system.
A terminal and a shell are closely related, but they are not the same thing.
+-----------------------------+
| Terminal Emulator |
| |
| +-----------------------+ |
| | Shell | |
| | e.g., bash or zsh | |
| +-----------------------+ |
| |
+-----------------------------+
The terminal is the window or application where you type commands.
The shell is the program running inside that terminal that understands and executes those commands.
A simple way to remember the difference is:
Terminal = where you type
Shell = what understands what you type
Examples of terminal emulators include GNOME Terminal, Konsole, xterm, Terminator, iTerm2, and Windows Terminal.
Examples of shells include Bash, Zsh, Sh, Ksh, and Tcsh.
There are several shells available on Unix-like systems. Each one has its own strengths.
Bash stands for Bourne-Again SHell. It is one of the most common shells on Linux systems.
Bash is widely used because it is reliable, well documented, and available on most Linux distributions. Many tutorials and scripts assume Bash or a Bash-compatible shell.
A common Bash path is:
/bin/bash
Bash is a good shell for beginners because it is common, practical, and supported almost everywhere.
Zsh, or Z Shell, is popular for interactive terminal use. It includes helpful features such as improved tab completion, spelling correction, themes, and plugins.
A common Zsh path is:
/bin/zsh
Many users like Zsh because it can be customized heavily. Tools such as Oh My Zsh make it easier to manage themes and plugins.
Sh, or the Bourne shell, is one of the original Unix shells. It is simple and portable.
On many modern systems, /bin/sh may actually point to another shell, such as Dash or Bash in compatibility mode.
Sh is often used when writing portable scripts that should run on many Unix-like systems.
Ksh, or Korn shell, combines features from the Bourne shell and the C shell. It is powerful for scripting and has been used in many enterprise Unix environments.
It is less common today than Bash or Zsh, but it is still important on some systems.
Tcsh is an improved version of the C shell. It provides command-line editing and programmable completion.
It is less common than Bash or Zsh, but it may still appear on older systems or in specific Unix environments.
Linux and Unix-like systems usually store valid login shells in this file:
/etc/shells
To view the available shells, run:
cat /etc/shells
Example output:
/bin/sh
/bin/bash
/bin/dash
/bin/zsh
/usr/bin/zsh
This file matters because commands such as chsh, which changes your default shell, usually require the new shell to be listed in /etc/shells.
If a shell is not listed there, the system may refuse to use it as a login shell.
There are several ways to check which shell you are using. The methods are similar, but they do not always show exactly the same thing.
$SHELLecho "$SHELL"
This usually shows your default login shell.
Example:
/bin/bash
However, this does not always show the shell you are currently using. For example, your default shell may be Bash, but you might have started Zsh manually.
ps -p "$$" -o comm=
This is usually a better way to check the shell currently running.
Here:
$$
means “the process ID of the current shell.”
The command asks the system to show the command name for that process.
Example output:
bash
or:
zsh
$0echo "$0"
This prints the name of the current shell or script.
Example:
-bash
A leading dash, such as -bash, usually means the shell was started as a login shell.
You can switch shells temporarily or permanently.
To start another shell, type its name:
zsh
or:
bash
This starts a new shell session inside the current terminal.
To leave the temporary shell and return to the previous one, run:
exit
You can also press:
Ctrl + D
Temporary switching is useful when you want to test another shell without changing your account settings.
To change your default login shell, use chsh.
For example, to make Zsh your default shell:
chsh -s /bin/zsh
You may be asked for your password.
The change usually takes effect the next time you log out and log back in.
Before changing your shell, check that the shell appears in /etc/shells:
cat /etc/shells
Bash reads startup files when it starts. These files allow you to customize the shell.
You can use them to define aliases, environment variables, shell functions, prompt settings, history behavior, and other preferences.
Which files Bash reads depends on how the shell was started.
There are two important categories:
+-----------------------------+
| Login Shell |
| Example: SSH login |
| Reads login startup files |
+-----------------------------+
+-----------------------------+
| Interactive Non-Login Shell |
| Example: new terminal tab |
| Usually reads ~/.bashrc |
+-----------------------------+
A login shell is started when you log into a system. This can happen through a console login, an SSH session, or sometimes a terminal configured to start as a login shell.
When Bash starts as a login shell, it first reads:
/etc/profile
This is a global configuration file that can affect all users.
Then Bash looks for these user-specific files:
~/.bash_profile
~/.bash_login
~/.profile
Bash reads only the first one it finds.
The order is:
1. ~/.bash_profile
2. ~/.bash_login
3. ~/.profile
The startup flow looks like this:
Login Bash starts
|
v
Reads /etc/profile
|
v
Looks for user startup files
|
+--> ~/.bash_profile if found, read this and stop
|
+--> ~/.bash_login if found, read this and stop
|
+--> ~/.profile if found, read this
An interactive non-login shell is usually what you get when you open a new terminal window or tab after already logging into a desktop environment.
For this type of shell, Bash usually reads:
~/.bashrc
Some systems also read a system-wide Bash configuration file first, such as:
/etc/bash.bashrc
or:
/etc/bashrc
The flow usually looks like this:
New terminal window opens
|
v
Interactive non-login Bash starts
|
v
Reads system bashrc file if present
|
v
Reads ~/.bashrc
The ~/.bashrc file is especially important because it is commonly used for everyday interactive settings.
~/.bashrc Is Often Loaded from ~/.bash_profileA common issue is that login shells and non-login shells read different files.
For example, settings in ~/.bashrc may not load in a login shell. Settings in ~/.bash_profile may not load when opening a normal terminal window.
To make the shell behave consistently, users often source ~/.bashrc from ~/.bash_profile.
A typical ~/.bash_profile contains:
# ~/.bash_profile
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
This means:
If ~/.bashrc exists, load it.
The dot command:
. ~/.bashrc
means the same thing as:
source ~/.bashrc
Both commands run the contents of the file in the current shell.
~/.bashrcThe ~/.bashrc file is commonly used for settings that improve daily terminal use.
Typical contents include:
aliases
environment variables
shell functions
prompt settings
history settings
program shortcuts
A small example:
# ~/.bashrc
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
export EDITOR='nano'
export HISTSIZE=1000
export HISTFILESIZE=2000
PS1='\u@\h:\w\$ '
An alias is a shortcut for a command.
For example:
alias ll='ls -alF'
After defining this alias, typing:
ll
runs:
ls -alF
Aliases are useful for commands you type often.
Common examples:
alias ll='ls -la'
alias cls='clear'
alias grep='grep --color=auto'
alias ..='cd ..'
To view all aliases currently defined:
alias
To check whether a specific alias exists:
alias cat
To remove an alias temporarily:
unalias ll
This only removes the alias from the current shell session. To remove it permanently, delete or comment out the alias line in ~/.bashrc.
Environment variables are named values used by the shell and by programs started from the shell.
For example:
export EDITOR='nano'
This tells programs that need a text editor to use nano by default.
Another example:
export PATH="$HOME/bin:$PATH"
This adds the user’s bin directory to the command search path.
The PATH variable is especially important because it tells the shell where to look for programs when you type a command.
To view a variable:
echo "$PATH"
or:
echo "$EDITOR"
The export command makes a variable available to programs started from the shell.
Without export, the variable may only exist inside the current shell.
Bash remembers commands you have typed.
Two common history variables are:
HISTSIZE=1000
HISTFILESIZE=2000
HISTSIZE controls how many commands are kept in memory during the current session.
HISTFILESIZE controls how many commands are saved in the history file, usually:
~/.bash_history
To view your recent commands:
history
Command history is useful because you can reuse previous commands with the up and down arrow keys.
The shell prompt is the text shown before you type a command.
A prompt might look like this:
adam@linux:~/notes$
In Bash, the prompt is controlled by the PS1 variable.
Example:
PS1='\u@\h:\w\$ '
This means:
\u current username
\h hostname
\w current working directory
\$ $ for normal users, # for root
The prompt flow is:
PS1 value
|
v
Bash expands symbols like \u, \h, and \w
|
v
Prompt appears before each command
Prompt customization is useful because it can show helpful information such as the current directory, username, hostname, or Git branch.
A shell function is a reusable group of commands.
Functions are more powerful than aliases because they can accept arguments and contain multiple steps.
Example:
mkcd() {
mkdir -p "$1"
cd "$1"
}
After adding this to ~/.bashrc and reloading the file, you can run:
mkcd projects
This creates a directory named projects and immediately moves into it.
Here:
"$1"
means the first argument given to the function.
So in this command:
mkcd projects
projects becomes $1.
Aliases are best for simple shortcuts.
Example:
alias ll='ls -la'
Functions are better when you need arguments, conditions, or multiple commands.
Example:
backup() {
cp "$1" "$1.bak"
}
If you run:
backup notes.txt
the function creates:
notes.txt.bak
A good rule is:
Use an alias for a simple shortcut.
Use a function for reusable logic.
After editing ~/.bashrc, you do not always need to close and reopen the terminal.
You can reload it with:
source ~/.bashrc
or:
. ~/.bashrc
This applies changes to the current shell session.
For example, if you add:
alias ll='ls -la'
to ~/.bashrc, then run:
source ~/.bashrc
the alias becomes available immediately.
~/.bashrcHere is a practical example of a ~/.bashrc file:
# ~/.bashrc
# Load system-wide Bash settings if they exist
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# Useful aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
alias cls='clear'
# Environment variables
export EDITOR='nano'
export HISTSIZE=1000
export HISTFILESIZE=2000
# Prompt customization
PS1='\u@\h:\w\$ '
# Create a directory and move into it
mkcd() {
mkdir -p "$1"
cd "$1"
}
# Extract different archive types
extract() {
if [ -f "$1" ]; then
case "$1" in
*.tar.bz2) tar xjf "$1" ;;
*.tar.gz) tar xzf "$1" ;;
*.bz2) bunzip2 "$1" ;;
*.rar) unrar x "$1" ;;
*.gz) gunzip "$1" ;;
*.tar) tar xf "$1" ;;
*.tbz2) tar xjf "$1" ;;
*.tgz) tar xzf "$1" ;;
*.zip) unzip "$1" ;;
*.Z) uncompress "$1";;
*.7z) 7z x "$1" ;;
*) echo "Do not know how to extract '$1'" ;;
esac
else
echo "'$1' is not a valid file"
fi
}
The extract function checks the file extension and chooses the correct extraction command.
For example:
extract archive.zip
runs:
unzip archive.zip
This is useful because the user only needs to remember one command instead of many different archive commands.
A terminal emulator is a program that gives you access to a shell.
In the past, users interacted with Unix systems through physical terminals. Today, most users use graphical terminal emulator programs.
The relationship looks like this:
+------------------------------------------------+
| Terminal Emulator |
| |
| Displays text output |
| Accepts keyboard input |
| Handles tabs, panes, fonts, colors, shortcuts |
| |
| Inside it runs a shell such as Bash or Zsh |
+------------------------------------------------+
On many Linux desktop environments, a terminal can be opened with:
Ctrl + Alt + T
This shortcut may vary depending on the desktop environment or system settings.
You can also open a terminal from the application menu by searching for:
Terminal
or by selecting the installed terminal emulator.
Visual example:

This screenshot is a helpful reminder that the terminal can usually be launched either with a keyboard shortcut or from the application menu.
To list installed login shells:
cat /etc/shells
To show your default login shell:
echo "$SHELL"
To show the current shell process:
ps -p "$$" -o comm=
To show all aliases:
alias
To check a specific alias:
alias cat
To reload Bash settings:
source ~/.bashrc
To temporarily start Zsh:
zsh
To exit the current shell:
exit
To change the default shell:
chsh -s /bin/zsh
You can use the find command to search for files with profile in their name.
A basic command is:
find / -name '*profile*'
This searches from the root directory /.
However, searching the whole system may produce many permission errors. To hide permission errors, use:
find / -name '*profile*' 2>/dev/null
The part:
2>/dev/null
redirects error messages away from the terminal.
A safer and faster search in your home directory is:
find "$HOME" -name '*profile*'
Changing your default shell is usually safe if you choose a normal shell such as Bash or Zsh.
However, setting a user’s shell to a non-shell program can cause problems.
For example:
useradd -s /bin/tar username
This creates a user whose login shell is /bin/tar.
That is unusual and can prevent the user from having a normal interactive login session. It may be useful only in controlled experiments or restricted environments.
Do not test this on an important system unless you understand the consequences. It is better to use a virtual machine, container, or lab system.
cat. Use alias cat to see the aliases for cat.alias without any arguments.~/.bashrc in a text editor, add a new alias like alias ll='ls -la'. Save the file, reopen your terminal, and verify the new alias. To remove it, delete or comment out the line in ~/.bashrc, then save and restart your terminal.find command to search your system for files containing 'profile' in their name. Try find / -name '*profile*'.useradd -s /bin/tar username creates a user with /bin/tar as their shell. Be aware of the implications this may have on user interaction with the system.chsh -s /path/to/shell, then open a new terminal session and explore the new environment. Experiment with commands like alias, set, and declare -f to inspect custom variables, aliases, and functions.~/.bashrc file that automates a repetitive task (for example, a function that creates a directory and immediately changes into it). Reload your configuration and test the function. Explain the difference between an alias and a shell function.echo statements to ~/.profile, ~/.bash_profile, ~/.bashrc, and /etc/profile. Open both login and non-login shells and observe which files are sourced in each case. Summarize the loading sequence for each shell type.PS1 variable in your ~/.bashrc to display useful information such as the current user, hostname, working directory, and git branch (if applicable). Experiment with adding colors using ANSI escape codes and explain how each prompt component is defined.