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/sh for 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.

The command ls -la --sort=size /etc split into its parts: ls is the command name, -la and --sort=size are options, and /etc is the argument. ls -la --sort=size /etc name options argument which program how it behaves what it works on
One command line: the name, two options (a combined short option and a long option with a value) and one argument.

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 -l or -a. Several short options can be combined behind one dash: ls -la means ls -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 as cd usually have no man page of their own (they are described deep inside man bash); bash's help command explains them.
  • info: the GNU project keeps its longest manuals (for coreutils, bash, grep) in the Info format, with links between nodes. info coreutils is thorough, but most people use man day to day.
  • apropos (or man -k): searches the one-line descriptions of all man pages, for when you don't know the command's name. whatis (or man -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.