Introduction

The terminal is a text window into a shell — a program (on Ubuntu, usually bash) that reads the commands you type, runs them, and prints the result. Everything below is a command you type at the prompt and press Enter.
A few conventions used on this page:
  • <placeholder> means "replace this with your own value", e.g. <file>notes.txt.
  • Commands are grouped from beginner (navigation, files) to advanced (services, scheduling, SSH keys). You don't need to read it in order — jump to the section you need from the top or the right-hand outline.
  • Most commands here work on any Linux distribution; a few (like apt) are specific to Ubuntu/Debian.
man &lt;command&gt; || opens the manual page for &lt;command&gt; — the single most useful command on this page when you forget a flag | 'in1'
&lt;command&gt; --help || prints a short usage summary for most commands, without opening the full manual | 'in2'
clear || clears the terminal screen (or ctrl+l) | 'in3'

Navigation

pwd || prints the full path of the current directory (print working directory) | 'nav1'
ls || lists files and directories in the current directory | 'nav2'
ls -la || lists all files (including hidden dotfiles) in long format: permissions, owner, size, date | 'nav3'
ls -lh || long format with human-readable sizes (KB/MB/GB instead of bytes) | 'nav4'
cd &lt;directory&gt; || changes into &lt;directory&gt; | 'nav5'
cd .. || moves one directory up | 'nav6'
cd - || jumps back to the previous directory you were in | 'nav7'
cd || jumps to your home directory (same as cd ~) | 'nav8'
tree || shows the directory structure as a tree (install with sudo apt install tree) | 'nav9'
pushd &lt;directory&gt; / popd || pushes the current directory on a stack and jumps to &lt;directory&gt;, then pops back later — handy for bouncing between two directories | 'nav10'

Files & directories

touch &lt;file&gt; || creates an empty file, or updates its modified time if it already exists | 'file1'
mkdir &lt;dir&gt; || creates a new directory | 'file2'
mkdir -p &lt;a/b/c&gt; || creates nested directories in one go, without erroring if some already exist | 'file3'
cp &lt;source&gt; &lt;dest&gt; || copies a file | 'file4'
cp -r &lt;source_dir&gt; &lt;dest_dir&gt; || copies a directory recursively | 'file5'
mv &lt;source&gt; &lt;dest&gt; || moves or renames a file or directory | 'file6'
rm &lt;file&gt; || deletes a file (no trash bin — this is permanent) | 'file7'
rm -r &lt;dir&gt; || deletes a directory and everything in it, recursively | 'file8'
rm -rf &lt;dir&gt; || same as -r, but never prompts and ignores missing files — the classic "measure twice" command | 'file9'
rmdir &lt;dir&gt; || removes a directory, but only if it's empty | 'file10'
ln -s &lt;target&gt; &lt;link_name&gt; || creates a symbolic link (a pointer to another file/dir, like a shortcut) | 'file11'
cat &lt;file1&gt; &lt;file2&gt; &gt; &lt;merged&gt; || concatenates files together into a new file | 'file12'

Viewing & searching text

cat &lt;file&gt; || prints the whole file to the terminal | 'view1'
less &lt;file&gt; || opens the file for scrollable, searchable reading (q to quit, / to search) | 'view2'
head &lt;file&gt; || prints the first 10 lines of a file | 'view3'
tail &lt;file&gt; || prints the last 10 lines of a file | 'view4'
tail -f &lt;file&gt; || follows a file live as new lines are appended — the standard way to watch a log file | 'view5'
grep &lt;pattern&gt; &lt;file&gt; || prints lines in &lt;file&gt; matching &lt;pattern&gt; | 'view6'
grep -r &lt;pattern&gt; &lt;dir&gt; || searches for &lt;pattern&gt; recursively through every file in &lt;dir&gt; | 'view7'
grep -ri &lt;pattern&gt; &lt;dir&gt; || same as above, case-insensitive | 'view8'
wc -l &lt;file&gt; || counts the number of lines in a file | 'view9'
sort &lt;file&gt; || sorts the lines of a file alphabetically | 'view10'
sort -n &lt;file&gt; || sorts lines numerically instead of alphabetically | 'view11'
uniq || removes consecutive duplicate lines (usually piped after sort) | 'view12'
diff &lt;file1&gt; &lt;file2&gt; || shows the line-by-line differences between two files | 'view13'
sed 's/&lt;old&gt;/&lt;new&gt;/g' &lt;file&gt; || stream-edits a file, replacing every &lt;old&gt; with &lt;new&gt; | 'view14'
awk '{print $1}' &lt;file&gt; || prints the first whitespace-separated column of each line — awk is a full text-processing language, this is its most common use | 'view15'

Pipes, redirection & search

The terminal's real power comes from chaining small commands together instead of memorizing big ones.
<cmd1> | <cmd2> pipes the output of <cmd1> into the input of <cmd2>, e.g. ls -la | grep .conf
&lt;cmd&gt; &gt; &lt;file&gt; || redirects &lt;cmd&gt;'s output into &lt;file&gt;, overwriting it | 'pipe2'
&lt;cmd&gt; &gt;&gt; &lt;file&gt; || redirects &lt;cmd&gt;'s output into &lt;file&gt;, appending instead of overwriting | 'pipe3'
&lt;cmd&gt; &lt; &lt;file&gt; || feeds &lt;file&gt; in as &lt;cmd&gt;'s input | 'pipe4'
&lt;cmd1&gt; && &lt;cmd2&gt; || runs &lt;cmd2&gt; only if &lt;cmd1&gt; succeeded | 'pipe5'
&lt;cmd1&gt; ; &lt;cmd2&gt; || runs &lt;cmd2&gt; regardless of whether &lt;cmd1&gt; succeeded | 'pipe6'
find &lt;dir&gt; -name "&lt;pattern&gt;" || finds files/directories under &lt;dir&gt; matching &lt;pattern&gt;, e.g. find . -name "*.py" | 'pipe7'
find &lt;dir&gt; -type f -mtime -1 || finds files under &lt;dir&gt; modified in the last day | 'pipe8'
which &lt;command&gt; || shows the full path of the executable that would run for &lt;command&gt; | 'pipe9'
xargs builds and runs a command from piped-in input, e.g. find . -name "*.log" | xargs rm

Permissions & ownership

Every file has an owner, a group, and three permission sets (owner/group/others), each with read (r), write (w), and execute (x). ls -l shows them as a string like -rwxr-xr--.
chmod +x &lt;file&gt; || makes &lt;file&gt; executable for everyone | 'perm1'
chmod 755 &lt;file&gt; || sets permissions using octal notation: owner=rwx(7), group=rx(5), others=rx(5) | 'perm2'
chmod 644 &lt;file&gt; || common file permission: owner=rw(6), group=r(4), others=r(4) — no execute | 'perm3'
chown &lt;user&gt;:&lt;group&gt; &lt;file&gt; || changes the owner and group of a file | 'perm4'
chown -R &lt;user&gt;:&lt;group&gt; &lt;dir&gt; || changes ownership recursively for a whole directory | 'perm5'
sudo &lt;command&gt; || runs &lt;command&gt; with administrator (root) privileges | 'perm6'
sudo -i || opens a root shell (use with care) | 'perm7'

Package management (apt)

sudo apt update || refreshes the local list of available packages and versions (run this before installing anything) | 'pkg1'
sudo apt upgrade || upgrades all installed packages to their latest available version | 'pkg2'
sudo apt install &lt;package&gt; || installs a package | 'pkg3'
sudo apt remove &lt;package&gt; || uninstalls a package, keeping its configuration files | 'pkg4'
sudo apt purge &lt;package&gt; || uninstalls a package and its configuration files | 'pkg5'
sudo apt autoremove || removes packages that were installed as dependencies and are no longer needed | 'pkg6'
apt search &lt;term&gt; || searches package names and descriptions for &lt;term&gt; | 'pkg7'
apt show &lt;package&gt; || shows details about a package: version, size, dependencies | 'pkg8'
dpkg -l || lists all packages currently installed on the system | 'pkg9'

Processes & jobs

ps aux || lists all running processes on the system, with owner, CPU, and memory usage | 'proc1'
top || live, auto-refreshing view of running processes sorted by resource usage (q to quit) | 'proc2'
htop || a friendlier, colorized version of top (install with sudo apt install htop) | 'proc3'
kill &lt;pid&gt; || asks the process with ID &lt;pid&gt; to terminate gracefully | 'proc4'
kill -9 &lt;pid&gt; || force-kills a process immediately, no cleanup — last resort | 'proc5'
pkill &lt;name&gt; || kills all processes whose name matches &lt;name&gt;, without needing the PID | 'proc6'
&lt;command&gt; & || runs &lt;command&gt; in the background, freeing up the terminal | 'proc7'
jobs || lists background jobs started in the current terminal session | 'proc8'
fg / bg || brings a background job to the foreground, or resumes a stopped job in the background | 'proc9'
nohup &lt;command&gt; & || runs &lt;command&gt; in the background so it keeps running after you log out (output goes to nohup.out) | 'proc10'
ctrl+c || interrupts (stops) the currently running foreground command | 'proc11'
ctrl+z || suspends the currently running foreground command (resume with fg) | 'proc12'

System & disk info

uname -a || prints kernel name, version, and architecture | 'sys1'
lsb_release -a || prints the Ubuntu release name and version | 'sys2'
df -h || shows disk space usage for all mounted filesystems, in human-readable form | 'sys3'
du -sh &lt;dir&gt; || shows the total size of &lt;dir&gt;, human-readable | 'sys4'
du -sh * | sort -h shows the size of every item in the current directory, sorted smallest to largest
free -h || shows RAM and swap usage, human-readable | 'sys6'
lsblk || lists block devices (disks and partitions) as a tree | 'sys7'
uptime || shows how long the system has been running and the load average | 'sys8'
whoami || prints the current username | 'sys9'
id || prints the current user's UID, GID, and group memberships | 'sys10'

Networking

ip a || lists network interfaces and their IP addresses (modern replacement for ifconfig) | 'net1'
ping &lt;host&gt; || sends repeated packets to &lt;host&gt; to test connectivity/latency (ctrl+c to stop) | 'net2'
curl &lt;url&gt; || fetches a URL and prints the response body to the terminal | 'net3'
curl -O &lt;url&gt; || downloads the URL's content to a local file with the same name | 'net4'
wget &lt;url&gt; || downloads a file from &lt;url&gt; to the current directory | 'net5'
ssh &lt;user&gt;@&lt;host&gt; || opens a secure shell session on a remote machine | 'net6'
scp &lt;file&gt; &lt;user&gt;@&lt;host&gt;:&lt;path&gt; || copies &lt;file&gt; to &lt;path&gt; on a remote machine over SSH | 'net7'
rsync -avz &lt;source&gt; &lt;dest&gt; || syncs files/directories, only transferring what changed — the robust way to copy large trees, local or remote | 'net8'
ss -tulpn || lists listening network ports and the process using each one (modern replacement for netstat) | 'net9'

Archives & compression

tar -czvf &lt;archive.tar.gz&gt; &lt;dir&gt; || creates a compressed tarball from &lt;dir&gt; | 'arc1'
tar -xzvf &lt;archive.tar.gz&gt; || extracts a .tar.gz archive into the current directory | 'arc2'
tar -tvf &lt;archive.tar&gt; || lists the contents of a tar archive without extracting it | 'arc3'
zip -r &lt;archive.zip&gt; &lt;dir&gt; || creates a .zip archive from &lt;dir&gt; | 'arc4'
unzip &lt;archive.zip&gt; || extracts a .zip archive into the current directory | 'arc5'

Environment, shell config & aliases

bash reads ~/.bashrc every time you open a new terminal — it's the place to put aliases, environment variables, and prompt customizations you want to persist.
echo $&lt;VAR&gt; || prints the value of environment variable &lt;VAR&gt;, e.g. echo $PATH | 'env1'
export &lt;VAR&gt;=&lt;value&gt; || sets an environment variable for the current shell session (and anything launched from it) | 'env2'
env || lists all environment variables currently set | 'env3'
alias &lt;name&gt;='&lt;command&gt;' || creates a shortcut &lt;name&gt; for a longer &lt;command&gt;, e.g. alias ll='ls -la' | 'env4'
source ~/.bashrc || reloads your shell config file without opening a new terminal | 'env5'
history || lists previously run commands, numbered | 'env6'
!&lt;n&gt; || re-runs command number &lt;n&gt; from history | 'env7'
ctrl+r || searches command history interactively as you type | 'env8'
!! || re-runs the last command (common pattern: sudo !!) | 'env9'

Users & system administration

sudo adduser &lt;username&gt; || creates a new user account, interactively | 'user1'
sudo passwd &lt;username&gt; || sets or changes a user's password | 'user2'
sudo usermod -aG &lt;group&gt; &lt;username&gt; || adds &lt;username&gt; to &lt;group&gt; (e.g. sudo, docker) without removing existing groups | 'user3'
su - &lt;username&gt; || switches to another user's shell and environment | 'user4'
groups || lists the groups the current user belongs to | 'user5'

Advanced: services, scheduling & SSH keys

systemctl status &lt;service&gt; | https://www.freedesktop.org/software/systemd/man/systemctl.html | shows whether a system service is running, and its recent log lines | 'adv1'
sudo systemctl start &lt;service&gt; || starts a system service | 'adv2'
sudo systemctl enable &lt;service&gt; || makes a service start automatically on boot | 'adv3'
journalctl -u &lt;service&gt; -f || follows the live logs for a systemd service | 'adv4'
crontab -e || opens your personal cron table for editing, to schedule recurring commands | 'adv5'
crontab -l || lists your currently scheduled cron jobs | 'adv6'
A crontab line has five time fields (minute hour day month weekday) followed by the command, e.g. 0 3 * * * /home/me/backup.sh runs backup.sh every day at 3 AM.
ssh-keygen -t ed25519 -C "&lt;email&gt;" | https://www.ssh.com/academy/ssh/keygen | generates a new SSH key pair for passwordless login | 'adv7'
ssh-copy-id &lt;user&gt;@&lt;host&gt; || copies your public SSH key to a remote host's authorized_keys, enabling passwordless login | 'adv8'
watch -n &lt;seconds&gt; &lt;command&gt; || re-runs &lt;command&gt; every &lt;seconds&gt; and shows the output live, e.g. watch -n 2 df -h | 'adv9'
strace -f -e trace=open,openat &lt;command&gt; || traces the system calls a command makes — useful for debugging "why can't it find this file" | 'adv10'
lsof -i :&lt;port&gt; || shows which process is listening on &lt;port&gt; | 'adv11'
screen -S <name> starts a named terminal-multiplexer session that survives disconnects (see the tmux page for the more modern alternative)

related topics

Debugging: gdb, pdb & a General Method — debugging tools you'll reach for from this same terminal.
Git Cheat Sheet — the git commands you'll run constantly from this terminal.

reference

Ubuntu: Command line for beginners
GNU Bash Reference Manual
explainshell.com — paste a command to see every part explained