Chapter 1. Essential Concepts
What’s Linux?
Linux is a free, open source operating system (OS) that’s an alternative to Microsoft Windows and Apple macOS. Linux powers most of the servers on the internet. It operates behind the scenes on every Android mobile phone and Chromebook, and on millions of network-connected devices like routers, firewalls, and robotic cow-milking systems (seriously). It also runs fine on desktop and laptop computers.
Linux has four major parts, shown in Figure 1-1:
- The kernel
-
Low-level software. It controls the hardware and basic functions like process scheduling and networking. Few users interact with the kernel directly.
- Supplied programs
-
Thousands of programs for file handling, text editing, software development, web browsing, audio, video, encryption, mathematics…you name it. These programs talk to the kernel. Programs that run on the command line are called commands.
- The shell
-
A Linux program for running commands and displaying the results. Linux has an assortment of shells with different features. This book focuses on a shell called bash, which is often the default for user accounts. Some other shells are dash, fish, ksh (Korn shell), tcsh (TC shell, or T shell), zsh (Z shell), and to a lesser extent, busybox. All shells have similar functions, though their usage varies.
- Graphical desktop environment (optional)
-
A UI with windows, menus, icons, mouse support, and other familiar GUI elements. Some popular environments are GNOME and KDE Plasma. Most applications built for GNOME can run in KDE and vice versa.1
This book focuses on the command-line parts of Linux, namely the
supplied programs and the shell. Windows and macOS have command-line
interfaces too (cmd
and powershell
on Windows, Terminal on the
Mac), but most of their users stick with the GUI and might never see
or need a command line. On Linux, the shell is critical. If you use
Linux without the shell, you are missing out.
Linux is extremely configurable and comes in hundreds of varieties that serve different needs and tastes. Each variety is called a distro (short for “distribution”). All distros share some core components but may look different and include different programs and files. Some popular distros include Mint, Ubuntu, Manjaro, Arch, Gentoo, Red Hat, and OpenSUSE, among others. The core material in this book should apply to every distro.
Launching a Shell
Where do shells come from? Sometimes Linux will launch one for you
automatically. This is often the case when you
log in over a network using ssh
or a similar tool.
The first significant thing you see is a shell prompt awaiting your
command.
Other times, you have to launch a shell manually. This is common when using a graphical desktop full of icons and menus with no shell in sight. In such cases, you need a GUI application called a terminal or terminal program that runs shells in a window. The sidebar “Shell Versus Terminal” clarifies the difference between shells and terminals.
Every distro with a graphical desktop includes at least one terminal
program, but you might have to hunt for it. Search for an application,
icon, or menu item named Terminal, Konsole,
xterm, gnome-terminal,
uxterm, or something similar, and run it to open a
terminal. Also try pressing Ctrl-Alt-t
(hold the Control and Alt
keys and press T
), which opens a terminal in some environments.
Command-Line Warm-Up
To give you a feel for Linux, here are 10 simple commands to try right now in a shell. Type them exactly, including capital and small letters, spaces, and all symbols after the prompt. At the end of each command, press Enter.2
Display a calendar for November 2023:
→ cal nov 2023 November 2023 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
List the contents of the /bin directory, which contains many commands:
→ ls /bin bash less rm bunzip2 lessecho rmdir busybox lessfile rnano ⋮
Count the number of visible items in your home directory (represented
here by a variable, HOME
, that I discuss later):
→ ls $HOME | wc -l
8 Your value may be different
See how much space is used on a partition of your hard disk:
→ df -h / Filesystem Size Used Avail Use% Mounted on /dev/sdb1 78G 30G 48G 61% /
Watch the processes running on your computer (press “q” to quit):
→ top -d1
Print the file /etc/hosts, which contains names and addresses of computers, on your default printer if you have one set up:
→ lpr /etc/hosts
See how long you’ve been logged in:
→ last -1 $USER smith pts/7 :0 Tue Nov 10 20:12 still logged in
Download a file sample.pdf from this book’s website to your current directory, without needing a web browser:
→ curl -O https://linuxpocketguide.com/sample.pdf
See who owns the domain name oreilly.com (press the space bar to move forward page by page, and press “q” to quit):
→ whois oreilly.com | less Domain Name: OREILLY.COM Registrar: GODADDY.COM, LLC ⋮
Finally, clear your terminal or screen:
→ clear
The Structure of Commands
A Linux command typically consists of a program name followed by options and arguments:
wc -l myfile
The program name (wc
, short for “word count”) refers to a program
somewhere on disk that the shell locates and runs. Options, which
usually begin with a dash, affect the behavior of the program. In the
preceding command, the -l
option tells wc
to count lines and not
words. The argument myfile
specifies the file that wc
should read
and process.
Commands can have multiple options and arguments. Options may be given individually, or combined after a single dash:
wc -l -w myfilewc -lw myfile
Two individual options
Combined options, same as -l -w
though some programs are quirky and do not recognize combined options. Multiple arguments are also OK:
wc -l myfile myfile2 Count lines in two files
Options are not standardized. They may be a single dash and one
character (say, -l
), two dashes and a word (--lines
), or several
other formats. The same option may have different meanings to
different programs: in the command wc -l
, the option -l
means
“lines of text,” but in ls -l
it means “long output.” Two programs
also might use different options to mean the same thing, such as -q
for “run quietly” versus -s
for “run silently.” Some options are
followed by a value, such as -s 10
, and space between them might not
be required (-s10
).
Arguments are usually filenames for input or output, but they can be other things too, like directory names, usernames, hostnames, IP addresses, regular expressions, or arbitrary strings.
A command that’s just a single program with options and arguments is called a simple command. Here’s a simple command that lists users who are logged into a Linux server:3
→ who silver :0 Sep 23 20:44 byrnes pts/0 Sep 15 13:51 barrett pts/1 Sep 22 21:15 silver pts/2 Sep 22 21:18
A command can also invoke several programs at once and even connect
programs so they interact. Here’s a command that connects the output
of who
to the input of wc
, which counts lines of text. The result
is the number of lines in the output of who
:
→ who | wc -l 4
The vertical bar, called a pipe, makes the connection between who
and wc
. Linux
experts use these sorts of combined commands, called pipelines, all
the time.
Commands can also include programming language constructs like variables, conditionals, and loops, which I cover in “Programming with Shell Scripts”. For example, a command might say, “run this program, write its output to a file of my choosing, and if any errors occur, send me an email with the results.”
Users and Superusers
Linux is a multiuser OS: multiple people can run
programs on a single Linux computer at the same time. On a given
computer, each user is identified by a username, like smith
or
funkydance
. Each user has a separate workspace of sorts (see
“Home Directories”) so they don’t interfere with one another.
A special user named root—the superuser or administrator—has the privileges to do anything at all on the system. The superuser can create, modify, or delete any file and run any program. Ordinary users are restricted: they can run most programs, but in general, they can’t mess with other users’ stuff.
Some commands in this book require superuser privileges. I precede
these commands with sudo
:
→ sudo superuser command goes here
Warning
sudo
gives you the power to destroy your Linux system.
I discuss sudo
fully in “Becoming the Superuser”, but for now,
all you need to know is that sudo
gives you superuser powers and
sometimes prompts for your password. For example, to count lines
in a protected file called /etc/shadow, with and without sudo
, you
could run this command:
→ wc -l /etc/shadowwc: /etc/shadow: Permission denied → sudo wc -l /etc/shadow
This fails
[sudo] password: xxxxxxxx 51 /etc/shadow
Run with sudo
It worked!
The Filesystem
To make use of any Linux system, you must become comfortable with
Linux files and directories (a.k.a. folders),
collectively called the filesystem. On a graphical
desktop, files and directories are obvious on screen. In a
command-line interface like the Linux shell, the same files and
directories are still present but less visible, so at times you must
remember which directory you are “in” and how it relates to other
directories. You’ll use shell commands like cd
(change directory) to move between directories, and commands like
pwd
(print working directory) to keep track of
where you are in the filesystem.
Let’s cover some terminology. Linux files are collected into directories. The directories form a hierarchy, or tree, as in Figure 1-3. One directory may contain other directories, called subdirectories, which may themselves contain other files and subdirectories, and so on, into infinity. The topmost directory is called the root directory and is denoted by a slash (/).4
Linux refers to its files and directories using a “names and slashes” syntax called a path. For instance, the following path:
/one/two/three/four
refers to the root directory /, which contains a directory called one, which contains a directory two, which contains a directory three, which contains a final file or directory, four. Any path that begins with a slash, which descends all the way from the root, is called an absolute path.
Paths don’t have to be absolute—they can be relative to some directory other than the root. Figure 1-3 has two different directories named bin, whose absolute paths are /bin and /usr/bin. If you simply refer to “the bin directory,” it’s not clear which one you mean. You need more context. Any path that doesn’t begin with a slash, like bin, is called a relative path.
To make sense of a relative path, you need to know “where you are” in the Linux filesystem. This location is called your current directory (sometimes called “working directory” or “current working directory”).
Every shell has a current directory, and when you run commands in that shell, they operate relative to its current directory. For example, if your shell is “in” the directory /usr, and you refer to a relative path bin, it means /usr/bin. In general, if your current directory is /one/two/three, a relative path a/b/c would imply the absolute path /one/two/three/a/b/c.
Two special relative paths are named .
(a single period, or
“dot”) and ..
(two periods, or
“dot dot”). “Dot” means
your shell’s current directory, and “dot dot” means its parent directory,
one level above. So if your shell’s current directory is /one/two/three,
then .
refers to this directory and ..
refers to /one/two.
To travel from one directory to another, use the cd
command, which changes your shell’s current directory:
→ cd /usr/local/bin Enter the directory /usr/local/bin
The previous cd
command used an absolute path. You can make relative
moves with cd
as well:
→ cd d→ cd ../mydir
Enter subdirectory d of my current directory
Go up to my parent, then into directory mydir
File and directory names may contain most characters you expect: capital and small letters,5 numbers, periods, dashes, underscores, and most symbols (but not “/”, which is reserved for separating directories). For efficiency, however, avoid spaces, asterisks, dollar signs, parentheses, and other characters that have special meaning to the shell. These characters require special treatment in filenames (see “Quoting”), which can be inconvenient or tedious.
Home Directories
Users’ personal files are usually kept in the directory /home (for ordinary users) or /root (for the superuser). Your home directory is typically /home/<your-username> (/home/smith, /home/funkydance, etc.). There are several ways to visit or refer to your home directory:
cd
-
With no arguments, the
cd
command returns you (i.e., sets the shell’s current directory) to your home directory. HOME
variable-
The environment variable
HOME
(see “Shell Variables”) contains the name of your home directory:→ echo $HOME
/home/smith → cd $HOME/linuxpocketguidePrint the directory name
Visit a subdirectory
~
-
When used in place of a directory, a lone tilde is expanded by the shell to the name of your home directory.
→ echo ~
/home/smith → cd ~/linuxpocketguidePrint the directory name
Visit a subdirectory
When the tilde is followed by a username (as in ~fred), the shell expands this string to be the user’s home directory:
→ cd ~fred
→ pwdVisit Fred's home directory, if it exists
/home/fredThe “print working directory” command
System Directories
A Linux system has tens of thousands of system directories. They contain OS files, applications, documentation, and just about everything except personal user files (which typically live in /home).
Unless you’re a system administrator, you’ll rarely visit most system directories—but with a little knowledge you can understand or guess their purposes. Their names often contain three parts, as shown in Figure 1-4.
Directory path part 1: scope
The scope of a directory path describes, at a high level, the purpose of an entire directory tree. Some common ones are:
/ |
(Pronounced “root”) System files supplied with your distro |
/usr |
(Pronounced “user”) More system files supplied with your distro |
/usr/local |
(Pronounced “user local”) System files that are not supplied with your distro; they may be unique to your local Linux network or your individual computer |
There isn’t a clear distinction between / and /usr in practice, but / is considered “lower level” and closer to the OS.
Directory path part 2: category
The category of a directory path in Figure 1-4 describes the types of files found in a directory. For example, if the category is lib, you can be reasonably sure that the directory contains library files for programming. If the category is bin, the contents are usually binary files—executable programs.
When you precede a category like bin with a scope, you
produce paths like /bin, /usr/bin, and /usr/local/bin. A
distro’s most fundamental system programs like ls
and cat
are
typically in
/bin, and other system programs are in
/usr/bin.6 /usr/local/bin contains locally installed programs not
included in your distro. These are not hard-and-fast rules but typical
cases.
Some common categories are as follows:
Categories for programs |
|
Programs (usually binary files) |
|
Programs (usually binary files) for superusers |
|
Libraries of code used by programs |
|
Categories for documentation |
|
Documentation |
|
info |
|
Documentation files (manual pages) displayed by the |
|
Program-specific files, such as examples and installation instructions |
|
Categories for configuration |
|
Configuration files for the system (and other miscellaneous stuff) |
|
Configuration files for booting Linux |
|
Configuration files for booting Linux; also rc1.d, rc2.d, … |
|
Categories for programming |
|
Header files for programming |
|
Source code for programs |
|
Categories for web files |
|
Scripts/programs that run on web pages |
|
Web pages |
|
Web pages, typically in users’ home directories |
|
Web pages |
|
Categories for display |
|
Fonts (surprise!) |
|
X11 |
|
Categories for hardware |
|
Device files for interfacing with disks and other hardware |
|
Mount points: directories that provide access to disks |
|
Mount points: directories that provide access to disks |
|
Categories for runtime files |
|
Files related to the state of the computer, updated frequently |
|
Lock files, created by programs to say, “I am running”; the existence of a lock file may prevent another program, or another instance of the same program, from performing an action |
|
Logfiles that track important system events, containing error, warning, and informational messages |
|
PID files, which contain the IDs of running processes; these files are often consulted to track or kill particular processes |
|
Files queued or in transit, such as outgoing email, print jobs, and scheduled jobs |
|
Directory path part 3: application
The application part of a directory path (Figure 1-4), if present, is usually the name of a program. For example, the directory /etc/systemd has scope root (/), category etc (configuration files), and application systemd. Since systemd is a service for configuring Linux machines, a good guess is that /etc/systemd contains configuration files for that service—and it does.
Kernel-Related Directories
Some directories support the Linux kernel, the lowest-level part of the Linux OS:
- /boot
-
Files for booting the system. The kernel lives here, typically in /boot/vmlinuz or a file of similar name.
- /lost+found
-
Damaged files that were rescued by a disk recovery tool.
- /proc
-
Files for currently running processes; for advanced users.
- /sys
-
Files for kernel internals; for advanced users.
The files in /proc and /sys provide views into the running kernel and have special properties. Files in /proc always appear to be zero-sized, read-only, and dated now, but their contents magically contain information about the Linux kernel:
→ ls -lG /proc/version -r--r--r-- 1 root 0 Oct 3 22:55 /proc/version → cat /proc/version Linux version 5.15.0-76-generic ...
Files in /sys also have misleading sizes and magical contents:
→ ls -lG /sys/power/state -rw-r--r-- 1 root 4096 Jul 8 06:12 /sys/power/state → cat /sys/power/state freeze mem disk
/proc and /sys are used mostly by system programs, but feel free to view them. Here are some examples:
File Permissions
A Linux system may have many user accounts. To maintain privacy and security, most users can access only some files on the system, not all. This access control is embodied in two questions:
- Who has permission?
-
Every file and directory has an owner who can do anything they want with it. Typically, a file’s owner is the user who created it. A superuser can change a file’s owner.
Additionally, a predefined group of users may access a file. Groups are defined by the system administrator and I cover them in “Group Management”.
Finally, a file or directory can be opened to all users who have accounts on the system. You’ll also see this set of users called the world or simply other.
- What kind of permission is granted?
-
File owners, groups, and the world may each have permission to read, write (modify), and execute (run) particular files. Permissions also extend to directories, which users may read (view files within the directory), write (create and delete files within the directory), and execute (enter the directory with
cd
).
To see the ownership and permissions of a file named myfile, run ls
-l
, described in
“Basic File Operations”:
→ ls -l myfile -rw-r--r-- 1 smith smith 1168 Oct 28 2015 myfile
To see the ownership and permissions of a directory named mydir, add
the -d
option:
→ ls -ld mydir drwxr-x--- 3 smith smith 4096 Jan 08 15:02 mydir
In the output, the file permissions are the 10 leftmost characters, a
string of r
(read), w
(write), x
(execute), other letters, and
dashes. For example:
-rwxr-x---
Here’s what these letters and symbols mean, briefly:
Position | Meaning |
---|---|
1 |
File type: |
2–4 |
Permissions for the file’s owner: read ( |
5–7 |
Permissions for the file’s group: |
8–10 |
Permissions for all other users: |
My example -rwxr-x---
means a file that can be read, written, and
executed by the owner; read and executed by the group, but not
written; and not accessed at all by other users. To change the owner,
group, or permissions, use the commands chown
,
chgrp
, and chmod
,
respectively, as described in “Properties of Files”.
Selected Features of Bash
A shell does much more than simply run commands. It also simplifies
the running of commands, thanks to powerful features: pattern matching
for filenames, a “command history” to recall previous commands
quickly, pipes to send the output of one command to the input of
another, variables to store values for use by the shell, and
more. Take the time to learn these features, and you will become
faster and more productive with Linux.7 Let’s skim the
surface and introduce you to these useful tools. (For full
documentation, run info bash
.)
Which Shell Are You Running?
This book assumes that your shell is bash. To identify your shell, run:
→ echo $SHELL /bin/bash
If your shell isn’t bash and you wish to try it, run the command
bash
directly, because bash, like all shells, is just a
program. (It’s located at
/bin/bash.)
→ bash
Run the command exit
when done to return to your regular shell. To
change your default shell to bash, see the chsh
command
in “User Account Management”.
Pattern Matching
Pattern matching in the shell, sometimes called wildcards, is a shorthand to work
with sets of files. For example, the pattern a*
refers to files whose names begin with lowercase “a.” The
shell expands a pattern into the full set of filenames it matches. If
you run:
→ ls a* aardvark adamantium apple
the shell invisibly expands the pattern a*
into the filenames that
begin with “a” in your current directory, as if you had typed:
→ ls aardvark adamantium apple
ls
never knows you used a pattern: it sees only the final list of
filenames after expansion. This means every Linux program you launch
from a shell, regardless of its origin, “works” with patterns and
other shell features. This is a critically important point. A
surprising number of Linux users think that programs expand their own
file patterns on the command line. They don’t. The shell does it
before the associated program even runs.
Patterns never match two special characters: a leading period and the
directory slash (/
). These characters must be given literally.
A pattern like .bas*
matches .bashrc, and /etc/*conf
matches
all filenames ending in conf in the /etc directory.
To match a literal dash in a character set, put it first or
last so it’s not part of a range. To include a literal closing square
bracket in the set, put it first in the set, or escape it with a
backslash (\]
). To include a ^
or !
symbol literally, place
it somewhere other than first in the set, or escape it.
Brace Expansion
Similar to file patterns, expressions with curly braces also expand to become multiple arguments to a command. The comma-separated expression:
{bubble,quick,merge}
expands first to bubble
, then quick
, and finally merge
within a
command line, like this:
→ echo {bubble,quick,merge}sort.java bubblesort.java quicksort.java mergesort.java
Note
The key difference between braces and square brackets is that braces work with any strings, whereas square bracket expressions match only existing filenames.
Curly braces can also expand to a sequence of values in a range, if you
separate the endpoints of the range with two dots (..
):
→ echo {3..12} 3 4 5 6 7 8 9 10 11 12 → echo {A..E} A B C D E → echo file{1..5}.py file1.py file2.py file3.py file4.py file5.py
Shell Variables
You can define variables in a shell and assign them values:
→ MYVAR=3 Assign the value 3 to variable MYVAR
To refer to a value, simply place a dollar sign in front of the variable name:
→ echo $MYVAR 3
The shell defines some standard variables when you log in:
Variable | Meaning |
---|---|
Your home directory, such as /home/smith |
|
Your login name, such as |
|
Your incoming mailbox, such as /var/spool/mail/smith |
|
Your shell’s previous directory, prior to the last |
|
Your shell search path: directories separated by colons |
|
Your shell’s current directory |
|
The path to your shell (e.g., /bin/bash) |
|
The type of your terminal (e.g., xterm or vt100) |
|
Your login name |
Variables and their values are limited, by default, to the shell that
defines them. To make a variable and its value available to other
programs your shell invokes (i.e., subprocesses), use
the export
command:
→ MYVAR=3 → export MYVAR
or the shorthand:
→ export MYVAR=3
Your exported variable is now called an environment variable. To go further and make a variable available to every new shell you run, not just subprocesses of your current shell, place the variable definition beforehand in a shell configuration file; see “Tailoring Shell Behavior”.
To list a shell’s environment variables, run:
→ printenv
To set an environment variable just for the duration of one command,
prepend variable=
value to the command line:
→ printenv HOME
/home/smith
→ HOME=/home/sally printenv HOME
/home/sally
→ printenv HOME
/home/smith The original value is unaffected
Search Path
Programs may be scattered all over the Linux filesystem, mostly in directories like /bin and /usr/bin. When you run a command that invokes a program, somehow the shell must locate the program in the filesystem:
→ who The shell must locate the “who” program to run it
The shell finds the program by consulting the value of the environment
variable PATH
, which is a list of directories separated by colons.
This list is called the shell’s search path.
→ echo $PATH
/usr/local/bin:/bin:/usr/bin Search path with 3 directories
The shell looks for an executable file named who
in each listed
directory in sequence. If it locates who
(say, in /usr/bin/who),
it executes the program, and also caches the location for next time
(run hash --help
for more on caching). Otherwise, it reports a
failure:
bash: who: command not found
To print a command’s location in your search path, run the
type
or which
command:
→ type whowho is hashed (/usr/bin/who)
The output may vary:
who is /usr/bin/who
This means "who" is cached
→ which who /usr/bin/who
This means "who" isn't cached
To add directories to your shell’s search path temporarily, modify its
PATH
variable. For example, append /usr/sbin to your shell’s
search path:
→ PATH=$PATH:/usr/sbin → echo $PATH /usr/local/bin:/bin:/usr/bin:/usr/sbin
This change affects only the current shell. To make it stick, modify
PATH
in a bash configuration file, as explained in
“Tailoring Shell Behavior”. Then log out and log back in, or run
the configuration file by hand in each open shell window. For example:
→ . $HOME/.bashrc If you modified $HOME/.bashrc
Aliases
The alias
command defines a convenient
shorthand for another command. For example, this alias:
→ alias ll='ls -lG'
defines a new command ll
that runs ls -lG
:
→ ll total 436 -rw-r--r-- 1 smith 3584 Oct 11 14:59 file1 -rwxr-xr-x 1 smith 72 Aug 6 23:04 file2 ⋮
Define aliases in your ~/.bashrc file (see “Tailoring Shell Behavior”) to make them
available to future shells.8 To list all your aliases, run
alias
. If you want more flexibility than aliases provide, see
“Programming with Shell Scripts”, run info bash
, and read up on
“shell functions.”
Built-in Commands
Most Linux commands are programs in the Linux filesystem. Examples are
wc
and who
, which usually live in the directory /usr/bin. The
shell locates and runs them using the PATH
variable, as I described
in “Search Path”. Some other commands, however, are built-in
features of the shell, known as built-in commands. You’ve seen several built-in
commands in this chapter, such as cd
, alias
, and export
. To
determine whether a command is in the filesystem, a built-in command,
or an alias, run the type
command:
→ type wc cd llwc is /usr/bin/wc
Print the types of these commands
cd is a shell builtin
A program in the filesystem
ll is aliased to `ls -lG'
A built-in shell command
An alias
Input, Output, and Redirection
Most Linux commands accept input and/or produce output. Keyboard input is called standard input or stdin. Output to your display is called standard output or stdout. Error messages are treated specially and printed on standard error or stderr, which also is usually your display, but Linux separates stderr from stdout internally.9
The shell can redirect standard input, standard output, and standard
error to and from files. In other words, any command that reads from
standard input can have its input come from a file instead with the
shell’s <
operator:
→ command < infile
Likewise, any command that writes to standard output can write to a file instead:
→ command > outfile→ command >> outfile
Create/overwrite outfile
Append to outfile
A command that writes to standard error can have its error output redirected to a file as well, leaving standard output unaffected:
→ command 2> errorfile
To redirect both standard output and standard error to files:
→ command > outfile 2> errorfile→ command &> outfile
Separate files
→ command >& outfile
Single file (preferred)
Single file (less common)
Combined Commands
Bash lets you move beyond simple commands by combining multiple programs on a single command line.
Sequences of commands
To invoke several commands in sequence on a single command line, separate them with semicolons:
→ command1 ; command2 ; command3
To run a sequence of commands as before, but stop execution if any of
them fails, separate them with &&
(“and”) symbols:
→ command1 && command2 && command3
To run a sequence of commands, stopping execution as soon as one
succeeds, separate them with ||
(“or”) symbols:
→ command1 || command2 || command3
Pipes
You can redirect the standard output of one command to be the standard input of another, using the shell’s pipe (|) operator. (On US keyboards, find this symbol just above the Enter key.) For example, this command:
→ who | sort
sends the output of who
into the sort
command, printing an
alphabetically sorted list of logged-in users. Multiple pipes
work too. Let’s sort the output of who
again, extract the first
column of information (using awk
), and display the results one page
at a time (using less
):
→ who | sort | awk '{print $1}' | less
Command substitution
If you surround a command with backquotes (“backticks”), the shell removes the command and substitutes the command’s output.
→ date +%Y Print the current year 2024 → echo This year is `date +%Y` This year is 2024
A dollar sign and parentheses are equivalent to backquotes:
→ echo This year is $(date +%Y) This year is 2024
but are superior because they can be nested:
→ echo Next year is $(expr $(date +%Y) + 1) Next year is 2025
Process substitution
Some programs don’t work well with pipes because they don’t read from
standard input, only from disk files. An example is the diff
command
that compares two files line by line and prints their differences.
Process substitution is a way to force a
command like diff to read from standard input. It runs a command and
lets its output “masquerade” as a file, which programs like
diff will happily accept. With the process
substitution operator,
<()
, you can compare the output of
two commands instead of two disk files.
Suppose you have a directory full of JPEG and text files in pairs:
→ ls jpegexample file1.jpg file2.jpg file3.jpg ... file1.txt file2.txt file3.txt ...
and you want to confirm that every JPEG file has a corresponding text
file and vice versa. Ordinarily, you might create two temporary files,
one containing the JPEG filenames and the other containing the text
filenames, remove the file extensions with cut
, and compare the two
temporary files with diff
:
→ cd jpegexample → ls *.jpg | cut -d. -f1 > /tmp/jpegs → ls *.txt | cut -d. -f1 > /tmp/texts → diff /tmp/jpegs /tmp/texts 5a6 > file6 No file6.jpg was found 8d8 < file9 No file9.txt was found
Process substitution performs the same task with a single command and no temporary files:
→ diff <(ls *.jpg|cut -d. -f1) <(ls *.txt|cut -d. -f1)
Each <()
operator stands in for a filename on the command line, as
if that “file” contained the output of ls
and cut
.
Preventing Evaluation
The shell evaluates every character of a command. To prevent evaluation, use quoting or escaping.
Quoting
Normally, the shell treats whitespace as a separator for strings on the command line. To make a string that contains whitespace (e.g., a filename with a space in it), surround it with single or double quotes, and the shell treats it as a unit. Single quotes treat their contents literally, while double quotes permit variables and other shell constructs to be evaluated:
→ echo 'The variable HOME has value $HOME' The variable HOME has value $HOME → echo "The variable HOME has value $HOME" The variable HOME has value /home/smith
Escaping
If a character has special meaning to the shell but you want it used
literally (e.g., *
as a literal asterisk rather than a file
pattern), precede the character with the backslash “\” character. This
is called escaping the special character:
→ echo a*aardvark adamantium apple → echo a\*
A file pattern
a* → echo "I live in $HOME"
A literal asterisk
I live in /home/smith → echo "I live in \$HOME"
Print a variable value
I live in $HOME
Print a literal dollar sign
You can also escape control characters (tabs, newlines, ^D
, etc.) to
have them used literally on the command line, if you precede them with
^V
. This is particularly useful for tab characters, which the shell
would otherwise use for filename completion (see
“Filename Completion”).
→ echo "There is a tab between here^V and here" There is a tab between here and here
Command-line Editing
Bash lets you edit the command line you’re working on, using keystrokes inspired by the text editors Emacs and Vim (see “Creating and Editing Files”). To enable command-line editing with Emacs keys, run this command (and place it in a bash configuration file to make it permanent):
→ set -o emacs
For vi (or Vim) keys:
→ set -o vi
Emacs keystroke | Vim keystroke (after ESC) | Meaning |
---|---|---|
|
|
Go to previous command |
|
|
Go to next command |
|
Search for a previous command interactively |
|
|
|
Go forward one character |
|
|
Go backward one character |
|
|
Go to beginning of line |
|
|
Go to end of line |
|
|
Delete next character |
|
|
Delete to beginning of line |
Command History
A shell can recall previous commands and re-execute them, a feature called command history. Try these useful history-related commands and expressions:
Command | Meaning |
---|---|
|
Print your history |
|
Print the most recent N commands in your history |
|
Clear (delete) your history |
|
|
|
Represents command number N in your history |
|
Represents the command you entered N commands ago |
|
Represents the last argument from the previous command. Great for checking that files are present before running a destructive command like → ls z*
zebra.txt zipfile.zip zookeeper
→ rm !$ |
|
Represents all arguments from the previous command: → ls myfile emptyfile hugefile emptyfile hugefile myfile → wc !* 18 211 1168 myfile 0 0 0 emptyfile 333563 2737540 18577839 hugefile 333581 2737751 18579007 total |
Filename Completion
In the middle of typing a filename, press the Tab key and the shell automatically completes the filename for you. If several filenames match what you’ve entered so far, the shell beeps, indicating the match is ambiguous. Immediately press Tab a second time and the shell presents the alternatives. Try this:
→ cd /usr/bin → ls un<Tab><Tab>
The shell displays all files in /usr/bin that begin with un, such as uniq and unzip. Enter a few more characters to disambiguate your choice and press Tab again.
Shell Job Control
|
List your jobs. |
|
Placed after a command, runs it in the background. |
|
Keystroke to suspend the current (foreground) job. |
|
Suspend a shell. |
|
Unsuspend a job: bring it into the foreground. |
|
Make a suspended job run in the background. |
|
Forget a job. |
All Linux shells have job control: the ability to run commands in the background (multitasking behind the scenes) and foreground (the active process at your shell prompt). A job is simply the shell’s unit of work. When you run a command interactively, your current shell tracks it as a job. When the command completes, the associated job disappears. Jobs are at a higher level than Linux processes; the Linux OS knows nothing about them. They are merely constructs of the shell. Here is some important vocabulary about job control:
- Foreground job
-
In a shell, a running job that occupies the shell prompt so you cannot run another command
- Background job
-
In a shell, a running job that doesn’t occupy the prompt, so you can run other commands in the same shell
- Suspend
- Resume
-
To cause a suspended job to start running in the foreground again
- Disown
-
To tell the shell to stop tracking the job; the underlying processes continue to run
jobs |
stdin |
stdout |
- file |
-- opt |
--help |
--version |
The built-in command jobs
lists the jobs running
in your current shell by number and name:
→ jobs [1]- Running emacs myfile &[2]+ Stopped ssh example.com
A background job
A suspended job
The integer on the left is the job number, and the plus sign
identifies the default job affected by the fg
(foreground) and bg
(background) commands.
& |
Placed at the end of a command line, the ampersand causes the given command to run as a background job:
→ emacs myfile & [2] 28090
The shell’s response includes the job number (2) and the process ID of the command (28090).
^Z |
Typing ^Z
in a shell, while a job runs in the foreground,
suspends that job. It simply stops running, but its state is
remembered:
→ sleep 10 Waits for 10 seconds
^Z
[1]+ Stopped sleep 10
→
Now you’re ready to run bg
to put the sleep
command into the
background, or fg
to resume it in the foreground. You could also
leave it suspended and run other commands.
suspend |
stdin |
stdout |
- file |
-- opt |
--help |
--version |
The built-in suspend
command pauses the current shell if possible, as if you’d applied
^Z
to the shell itself. For instance, if you create a superuser
shell with sudo
and want to return to your original
shell, suspend
pauses the superuser shell:
→ whoami smith → sudo bash[sudo] password: xxxxxxxx # whoami root # suspend
Run a superuser shell
[1]+ Stopped sudo bash → whoami
Suspend the superuser shell
smith
Back to the original shell
bg |
stdin |
stdout |
- file |
-- opt |
--help |
--version |
bg [%job] |
The built-in command bg
sends a suspended job to run in the
background. With no arguments, bg
operates on the most recently
suspended job. To specify a particular job (shown by the jobs
command), supply the job number or name preceded by a percent
sign:
→ bg %2→ bg %cat
Send job 2 to the background
Send job beginning with “cat” to the background
Some types of interactive jobs cannot remain in the background—for instance, if they are waiting for input. If you try, the shell suspends the job and displays:
[2]+ Stopped command line here
Now resume the job (with fg
) and continue.
fg |
stdin |
stdout |
- file |
-- opt |
--help |
--version |
fg [%job] |
The built-in command fg
brings a suspended or
backgrounded job into the foreground. With no arguments, it selects a
job, usually the most recently suspended or backgrounded one. To
specify a particular job (as shown by the jobs
command), supply the
job number or name preceded by a percent sign:
→ fg %2→ fg %cat
Bring job 2 into the foreground
Bring job beginning with “cat” into the foreground
disown |
stdin |
stdout |
- file |
-- opt |
--help |
--version |
disown [-ar] [-h] [%job] |
The built-in command disown
tells your current
shell to “forget” a job. The Linux processes behind the job keep running—you just can’t control them anymore with bg
, fg
, jobs
, and other
job-related commands. This is useful for long jobs that you don’t need
to interact with, or jobs that should keep running after your
shell exits. See also nohup
in “Controlling Processes”.
→ disown %2→ disown %cat
Forget job #2
→ disown -h %2
Forget job beginning with “cat”
→ disown -r
Mark job #2 to keep running after shell exits
→ disown -a
Forget all running jobs
Forget all jobs
Running Multiple Shells at Once
Job control can manage several commands at once, but only one can run in the foreground at a time. More powerfully, you can run multiple shells at once, each with a foreground command and any number of background commands.
If your Linux computer runs a window system such as KDE or GNOME, you
can easily run many shells at the same time by opening multiple shell
windows (see “Launching a Shell”). In addition, certain shell
window programs, such as KDE’s konsole
, can open multiple tabs
within a single window, each one running a shell.
Even without a window system—say, over an SSH network connection—you
can manage multiple shells at once. The tmux
command simulates multiple shell windows in an ordinary ASCII
terminal. Using special keystrokes, you can switch from one virtual
window to another at will. (Another such program is screen
, but tmux
is better maintained and easier to configure.)
To begin a session with tmux
, run:
→ tmux
A new shell launches with an extra status bar at the bottom of the
terminal, indicating that you’re running one virtual window. The
tmux
program provides 10 such windows by default, labeled from 0 to
9, that you may switch between. Each window runs a single shell at
first, but you can split a window into multiple “panes” to display
multiple shells at once. Try these keystrokes to get the hang of
tmux
:
-
In the current
tmux
window, runls
. -
Press
^Bc
(Ctrl-B, then press c).tmux
displays a fresh shell prompt in a second virtual window. The status bar changes to show two virtual windows numbered 0 and 1. -
In this second window, run a different command (say,
df
). -
Press
^Bn
and you’ll switch back to window 0, where your output fromls
is now visible again. -
Press
^Bn
a few more times to toggle between the two virtual windows. -
Press
^B%
to split the current window into two panes side by side. -
Press
^B"
to split the current pane into two, vertically. You’re now viewing three shells in separate panes.
Most aspects of tmux
are configurable in the file ~/.tmux_conf,
even the choice of ^B
as the prefix key. Here are common keystroke
commands:
Keystroke | Meaning |
---|---|
|
Display online help. Press “q” to quit. |
|
Create a window. |
|
Switch to window 0 through 9, respectively. |
|
Switch to the next window, numerically. |
|
Switch to the previous window, numerically. |
|
Switch to the most recently used window. |
|
Split into two panes side by side. |
|
Split into two panes top and bottom. |
|
Jump to the next pane. |
|
Jump to the pane to the left. |
|
Jump to the pane to the right. |
|
Jump to the pane above. |
|
Jump to the pane below. |
|
Display pane numbers for reference. |
|
Kill the current pane. |
|
Send a true Ctrl-B to your shell, ignored by |
|
Suspend |
|
“Detach” from a |
|
Terminate a shell in a window or pane. This is the ordinary “end of file” keystroke, explained in “Terminating a Shell”, which closes any shell. |
|
Kill all windows and terminate |
A few notes about running tmux
:
-
If shells within
tmux
are missing your aliases, variables, or other shell settings, that’s becausetmux
runs a login shell that does not source your .bashrc initialization file. It only sources your startup file (.bash_profile, .bash_login, or .profile). To correct this issue, append these lines to your startup file:# Source my .bashrc file if [ -f ~/.bashrc ]; then . ~/.bashrc fi
-
If you run a text editor,
tmux
captures all Ctrl-B keystrokes, even those intended as editing commands. Press^B^B
to send a true Ctrl-B to your editor. -
Don’t run
tmux
locally on a graphical desktop; run multiple shell windows instead. It’s easier and avoids a problem: if you’ve configured your shell to run commands on logout (for example, in the file ~/.bash_logout),tmux
’s shells will run those commands on exit, even though you haven’t logged out of the desktop. This may have unwanted effects on your desktop login session.
Killing a Command in Progress
To kill a foreground command immediately, press ^C
. Here I kill the cat
command as it prints a huge file:
→ cat hugefile Lorem ipsum dolor sit amet, consectetur adipiscing odio. Praesent libero. Sed cursus ante dapibus diam. quis sem at nibh elementum blah blah blah ^C →
To kill a background command, bring it into the foreground with fg
and then press ^C
:
→ sleep 50 & [1] 12752 → jobs [1]- Running sleep 50 & → fg %1 sleep 50 ^C →
or run the kill
command described in
“Controlling Processes”. The keystroke ^C
is a shell feature.
It has no effect on programs that “catch” ^C
and do not terminate,
like text editors and GUI applications. Use kill
for those.
Tailoring Shell Behavior
Several files in your home directory control the behavior of bash shells. The startup files .bash_profile, .bash_login, and .profile contain commands that run each time you log in. (Choose just one startup file and stick with it. I recommend .bash_profile because some other shells also use .profile.) Commands in the initialization file .bashrc run every time you launch an interactive shell, and commands in .bash_logout run each time you log out. All these files can set variables, run programs, print silly messages, or whatever you like. Other Linux shells use other configuration files as shown in Table 1-1.
Shell | On login | By other interactive shells | On logout |
---|---|---|---|
bash |
.bash_profile, .bash_login, |
.bashrc |
.bash_logout |
.profile |
|||
.config/fish/config.fish |
.config/fish/config.fish |
||
ksha |
.profile, .kshrc |
.kshrc |
|
.tcshrc, .cshrc, .login |
.tcshrc, .cshrc |
||
zsha |
.zshenv, .zprofile, .zlogin |
.zshenv, .zshrc |
.zlogout |
a To override these file paths with environment variables, see the manpage. |
Other shell configuration files live in /etc for system-wide control; see the respective manual page, or manpage, for each shell. All these configuration files are examples of shell scripts: executable files that contain shell commands. I cover this feature in more detail in “Programming with Shell Scripts”.
Getting Help
If you need more information than this book provides, here are several ways to get more help:
- Run the
man
command -
The
man
command displays documentation for a given program. For example, to learn about counting words in a file withwc
, run:→ man wc
To search for manual pages (manpages) by keyword for a particular topic, use the
-k
option followed by the keyword:→ man -k database
If the list of manpages is longer than the screen, pipe it to
less
to display it in pages (pressq
to quit):→ man -k database | less
- Run the
info
command -
The
info
command is an extended, hypertext help system covering many Linux commands.→ info ls
While
info
runs, some useful keystrokes are:-
To get help, press
h
-
To quit, press
q
-
To page forward and backward, use the space bar and Backspace key, respectively
-
To jump between hyperlinks, press Tab
-
To follow a hyperlink, press Enter
If
info
has no documentation on a given command, it displays the command’s manpage. For a listing of available documentation, typeinfo
by itself. To learn how to navigate the info system, runinfo info
.
-
- Use the
--help
option (if any) -
Many Linux commands respond to the option
--help
or-h
by printing a short help message. Try:→ wc --help
If the output is longer than the screen, pipe it into
less
:→ wc --help | less
- Examine the directory /usr/share/doc
-
This directory contains supporting documents for programs, usually organized by name and version. For example, files for the editor Emacs version 28 are likely found (depending on distro) in /usr/share/doc/emacs28.
- Distro-specific websites
-
Most Linux distros have an official site with documentation, discussion forums, and other resources. Search the web for your distro name (e.g., “Ubuntu”) to find its website. The Arch Linux wiki is particularly informative regardless of your distro.
- Linux help sites
-
Ask Linux questions at cunix.stakexchange.org, linuxquestions.org, itsfoss.community, and nixcraft.com.
- Web search
-
To decipher a Linux error message, paste it into a search engine, verbatim, optionally surrounded by double quotes.
This concludes my basic overview of Linux and the shell. Now let’s turn to the specifics of Linux commands. The rest of the book lists and describes the most useful commands to work with files, processes, users, networking, multimedia, and more.
1 GNOME, KDE, and other environments are built on a common windowing system that is either X or Wayland. To see which system you’re using, run the command echo $XDG_SESSION_TYPE
.
2 If you see an error message “command not found,” don’t worry: a command probably isn’t installed on your system. See “Installing Software Packages”.
3 User “silver,” who is listed twice, is running two interactive shells at once.
4 In Linux, all files and directories descend from the root. This is unlike Windows, in which different devices are accessed by drive letters.
5 Linux filenames are case-sensitive, so upper and lowercase letters are not equivalent.
6 Some distros no longer make these distinctions. Fedora, for example, makes /bin a symbolic link to /usr/bin.
7 Also see my follow-up book, Efficient Linux at the Command Line, to grow your skills.
8 Some setups use ~/.bash_aliases for this purpose.
9 For example, you can capture standard output in a file and still have standard error messages appear on screen.
Get Linux Pocket Guide, 4th Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.