The Shell and the Terminal
What a shell is, how a command is built from a name, options and arguments, and the habits that make the command line fast: help pages, tab completion and history.
Terminal, shell and console
Three words are often used as if they meant the same thing. They don't, and knowing the difference helps when something goes wrong.
- A terminal emulator is the program that draws a text window, sends your keystrokes to a program and shows what that program prints. It imitates the hardware terminals (a screen and keyboard on a serial cable) of the 1970s. Examples are GNOME Terminal (Ubuntu 24.04), Ptyxis (the default on Fedora 41+ and Ubuntu 25.10+), Konsole, Windows Terminal, the macOS Terminal and PuTTY. In daily speech it is simply "the terminal".
- The shell runs inside the terminal. It is the command interpreter: it prints a prompt, reads the line you type, works out what you mean (expanding wildcards and variables, finding the program) and starts it. The shell is the text-based kind of shell that the Operating Systems topic introduces.
- The console is the text screen attached directly to the machine: a monitor and keyboard on a server, the serial console of a network device, or the remote console that a hypervisor or cloud provider offers when the network is down. On many distributions Ctrl+Alt+F3 and the next few function keys switch to text-only virtual consoles.
So when you connect to a server with Secure Shell (SSH), your terminal emulator runs on your laptop and the shell runs on the server. That is why closing the window ends the session: the terminal disappears, and the shell that depended on it is told to stop.
Bash and other shells
Bash (Bourne Again Shell) is the shell
of the GNU project (GNU's Not Unix) and the default interactive
shell on almost every Linux distribution, including Ubuntu, Debian,
Fedora and Red Hat Enterprise Linux (RHEL). The name is a pun on the
original Unix Bourne shell, sh, which bash extends.
Everything on these pages is written for bash.
Other shells you will meet:
- zsh (Z shell): the default on macOS since 2019 (see macOS Essentials) and popular with developers. For everyday commands it behaves like bash; scripts can differ in details.
-
dash: a small, fast shell that Debian and Ubuntu
use as
/bin/shfor system scripts, not for your interactive login. - fish, ksh and tcsh: less common on servers.
The file /etc/shells lists the shells installed on a
system, and the variable $SHELL holds your login shell:
$ echo $SHELL
$ cat /etc/shells
/bin/bash # /etc/shells: valid login shells /bin/sh /usr/bin/sh /bin/bash /usr/bin/bash /bin/rbash /usr/bin/rbash /usr/bin/dash
The prompt
The prompt is the text the shell prints when it is ready for a command. The defaults tell you who you are, on which machine, and where:
| Prompt | Where you see it | Meaning |
|---|---|---|
ana@web01:~$ |
Debian, Ubuntu |
User ana on host web01, in her
home directory (~), as an ordinary user
($)
|
ana@web01:/var/log$ |
Debian, Ubuntu | The same user, now in /var/log |
[ana@web01 ~]$ |
RHEL, Fedora | The same information; RHEL shows only the last part of the directory |
root@web01:~# |
Any |
You are root: the # is a
warning that every command runs with full power
|
On these pages, command lines in terminal sessions start with
$ (ordinary user) or # (root). You type
only what comes after that character. The prompt itself is
set by the variable PS1, so on a customized system it
can look quite different.
Anatomy of a command
The shell splits the line you type into words at spaces. The first word is the command name; the rest are handed to that command, which decides what they mean. By convention they fall into two groups.
Options
A command option (also called a flag or switch) changes how a command behaves. It starts with a dash, and there are two styles:
-
Short options: one dash and one letter, such as
-lor-a. Several short options can be combined behind one dash:ls -lameansls -l -a. -
Long options: two dashes and a word, such as
--all. They are easier to read, which makes them a good choice in scripts and documentation. GNU tools offer both styles for most options.
Some options take a value: -n 2 or
-n2 in the short style, --lines=2 or
--lines 2 in the long style.
Arguments
A command argument (also
called an operand) is a word that tells the command what to work on:
usually a file or directory name, sometimes a user name, a host or a
piece of text. Many commands accept several arguments and work on
each in turn. Options normally come before arguments. GNU tools also
accept them after (ls /etc -l), but tools on other
systems such as macOS do not, so the habit "options first" works
everywhere.
The same program, called with different options. The example first
creates a small file with printf (which prints its
text, \n meaning a new line, and >
saves that output in a file):
printf 'web01\ndb01\nmail01\nweb02\n' > servers.txt
wc servers.txt # lines, words, bytes
wc -l servers.txt # short option: only lines
wc --lines servers.txt # the same, long option
wc -lw servers.txt # two short options combined
head -n 2 servers.txt # an option with a value
head --lines=2 servers.txt
4 4 24 servers.txt 4 servers.txt 4 servers.txt 4 4 servers.txt web01 db01 web01 db01
# starts a comment: the shell ignores everything after
it on that line. wc (word count) prints the number of
lines, words and bytes; the options choose which of those you get.
Printing text: echo and printf
Two commands print text, and you will use both constantly, on the
command line and in scripts. echo prints its arguments
separated by spaces, followed by a new line (unless you add
-n). printf takes a format string, as in C
or Python: %s for text, %d for a whole
number, %-8s for text padded to eight characters.
Unlike echo, it adds a new line only where you write
\n, and it behaves the same on every system, which
makes it the safer choice in scripts.
echo Hello from the shell
echo -n "No newline yet"; echo " ... now there is one"
printf '%s has %d open tickets\n' "Ana" 3
printf '%-8s %5s\n' "Server" "Load" "web01" "0.42" "db01" "1.87"
Hello from the shell No newline yet ... now there is one Ana has 3 open tickets Server Load web01 0.42 db01 1.87
A semicolon (;) separates two commands on one line.
When printf gets more arguments than its format uses,
it repeats the format, which is why the last line prints a small
table.
Programs and builtins
Most commands are separate programs: files in
directories such as /usr/bin. The shell finds them by
searching the directories listed in the variable PATH,
in order. A few commands are builtins, part of the
shell itself. They have to be: cd changes the shell's
own current directory, which a separate program could never do for
it. Others, such as echo, are builtins for speed.
type tells you what a name is, and
command -v prints what would run, in a form that
scripts can use:
type cd
type echo
type if
type ls
type -t cd
type -t ls
command -v cd
command -v ls
cd is a shell builtin echo is a shell builtin if is a shell keyword ls is /usr/bin/ls builtin file cd /usr/bin/ls
type -t answers in one word: builtin,
file (a program), alias,
function or keyword. The exact path of a
program can differ between distributions (/usr/bin/ls
or /bin/ls).
You will also see which. It only searches
PATH for programs, so it knows nothing about builtins
or aliases:
$ which ls
$ which cd
/usr/bin/ls
On Debian and Ubuntu, which cd prints nothing (the
exact behavior differs between versions of which). On
RHEL, Fedora and macOS it prints /usr/bin/cd: a small
wrapper script that exists only because the POSIX standard asks for
it. It runs the builtin cd in a separate process, so it
cannot change your shell's directory. Prefer type
when you want the truth about what the shell will run.
Getting help
Linux documents itself. Before searching the web, which may give you advice for another distribution or version, ask the system.
Manual pages
A man page (manual page) is the
reference documentation for a command, configuration file or
programming function, read with man:
man ls. Every page follows the same layout: NAME,
SYNOPSIS (the syntax, with optional parts in
[brackets] and repeatable parts marked
...), DESCRIPTION with every option, and often
EXAMPLES, FILES and SEE ALSO.
The manual is divided into numbered sections. When a name exists in
several sections, add the number:
passwd is both a command (section 1) and a file format
(section 5), so man 5 passwd explains the file
/etc/passwd.
| Section | Contains | Example |
|---|---|---|
| 1 | User commands | man 1 ls |
| 2 | System calls (kernel functions) | man 2 open |
| 3 | Library functions | man 3 printf |
| 4 | Special files, mostly in /dev |
man 4 null |
| 5 | File formats and configuration files | man 5 crontab |
| 6 | Games | |
| 7 | Overviews and conventions | man 7 regex |
| 8 | System administration commands (often need root) | man 8 useradd |
man shows the page in a pager (usually
less), so the same keys work everywhere:
| Key | Does |
|---|---|
| Space / b | One screen forward / back |
| ↓ ↑ or j k | One line down / up |
/word Enter |
Search forward for word |
| n / N | Next / previous match |
| g / G | Start / end of the page |
| h | Help for the pager itself |
| q | Quit |
A useful search inside a man page: /^ +-r jumps to the
line where option -r is described, because options are
listed indented at the start of a line.
--help, help, info and apropos
-
--help: almost every GNU program prints a short usage summary with all its options. Faster than the man page when you only need to remember one flag. -
help: builtins such ascdusually have no man page of their own (they are described deep insideman bash); bash'shelpcommand explains them. -
info: the GNU project keeps its longest manuals (for coreutils, bash, grep) in the Info format, with links between nodes.info coreutilsis thorough, but most people usemanday to day. -
apropos(orman -k): searches the one-line descriptions of all man pages, for when you don't know the command's name.whatis(orman -f) shows the one-line description of a name you do know.
help cd | head -n 1
head --help | head -n 1
cd: cd [-L|[-P [-e]] [-@]] [dir] Usage: head [OPTION]... [FILE]...
(| head -n 1 keeps only the first line; pipes are
explained in
Pipes, Redirection and Filters.)
$ apropos "directory contents"
$ whatis passwd
dir (1) - list directory contents ls (1) - list directory contents vdir (1) - list directory contents passwd (1) - change user password passwd (5) - the password file
apropos and whatis read an index that the
system rebuilds regularly (mandb). Minimal server and
container images sometimes leave man pages out altogether to save
space; then --help is your friend.
Working faster
Tab completion
Tab completion means pressing Tab to let the shell finish what you are typing: a command name, a file or directory name, and on most distributions also options, package names or service names (through the bash-completion package). If there is exactly one match, the shell completes it. If there are several, a second Tab lists them:
$ cd /etc/netp[Tab] becomes $ cd /etc/netplan/ $ ls /var/log/sy[Tab][Tab] syslog syslog.1 syslog.2.gz sysstat/
Tab completion is not only about speed. A name that completes is a name that exists, so it prevents typing mistakes in paths, and it takes care of awkward characters such as spaces for you.
Command history
The command history is the
list of commands you ran before, which bash keeps in memory and
saves to ~/.bash_history when the shell exits.
| Keys or command | Does |
|---|---|
| ↑ / ↓ | Step back and forward through earlier commands, ready to edit and run again |
| Ctrl+R | Reverse search: type part of an old command, press Ctrl+R again for older matches, Enter to run, → or Esc to edit first |
history |
Print the numbered list; history 20 shows the
last 20
|
!! |
Repeat the previous command |
!42 |
Run command number 42 from the list |
$ history 3
512 cd /var/log 513 tail -n 20 syslog 514 history 3
The classic use of !! is repeating a command that
failed with "Permission denied" through sudo:
sudo !!. Bash prints the expanded command before it
runs it, but it does not ask first.
Aliases
An alias is a short name that the shell
replaces with a longer command before running it. Many distributions
already define a few, such as ll for
ls -l (with extra options) on Ubuntu:
$ alias ll='ls -l'
$ alias rm='rm -i'
$ alias
$ unalias rm
An alias typed at the prompt disappears when the shell closes. To
keep it, add the line to ~/.bashrc, the file bash reads
whenever it starts an interactive shell, and run
source ~/.bashrc (or open a new terminal) to load it. A
login shell, such as an SSH session, reads
~/.profile (or ~/.bash_profile) instead;
on Debian and Ubuntu the default ~/.profile sources
~/.bashrc, so the alias works there too. A backslash
skips an alias for one command: \rm runs the real
rm.
Aliases are an interactive convenience: scripts ignore them unless
they switch them on with shopt -s expand_aliases, which
is why this example does that first.
shopt -s expand_aliases
alias l1='ls -1'
alias
mkdir tools
touch tools/backup.sh tools/notes.txt
l1 tools
type l1
unalias l1
type -t l1 || echo "l1 is gone"
alias l1='ls -1' backup.sh notes.txt l1 is aliased to `ls -1' l1 is gone
ls -1 (the digit one) lists one name per line.
|| runs the command on its right only if the one on its
left failed; type fails for a name it does not know.
Keys worth knowing
| Keys | Does |
|---|---|
| Ctrl+C | Interrupt the running command (or discard the line you are typing) |
| Ctrl+D | End of input: finishes typed input for a program that reads the keyboard, and on an empty prompt logs out of the shell |
| Ctrl+Z | Suspend the running command (see Processes and Jobs) |
| Ctrl+L | Clear the screen (like clear) |
| Ctrl+A / Ctrl+E | Jump to the start / end of the line |
| Ctrl+U / Ctrl+K | Delete from the cursor to the start / end of the line |
| Ctrl+W | Delete the word before the cursor |
| Alt+. | Insert the last argument of the previous command |
In most terminal emulators, copy and paste are Ctrl+Shift+C and Ctrl+Shift+V, because plain Ctrl+C already means "interrupt".
Case, spaces and quoting
Linux is case-sensitive everywhere: in command
names (LS is not ls), options (ls -r
reverses the order, ls -R lists recursively) and file
names (Notes.txt and notes.txt are two
different files).
Because the shell splits a line at spaces, a file name with a space in it arrives as two separate arguments, unless you quote it or put a backslash before the space:
mkdir reports
cd reports
touch Notes.txt notes.txt "annual report.txt"
ls -1
ls -1 annual report.txt
ls -1 "annual report.txt"
ls -1 annual\ report.txt
Notes.txt annual report.txt notes.txt ls: cannot access 'annual': No such file or directory ls: cannot access 'report.txt': No such file or directory annual report.txt annual report.txt
The examples ran with LC_ALL=C.UTF-8, which sorts by
byte value: capitals before lowercase. In English locales,
ls, glob sorting and sort ignore dots,
dashes and case at first, so your order may differ;
LC_ALL=C gives byte order.
Without quotes, ls looked for two files,
annual and report.txt, and found neither.
The same thing with rm could delete two files you did
not mean. Single quotes ('…') keep everything
literally; double quotes ("…") still allow variables
such as $HOME inside. The full rules are in
Shell Scripting Basics.