Linux Commands List: The 60 Commands You Actually Need, With Examples (2026)

Linux Commands List: The 60 Commands You Actually Need, With Examples (2026)

On our Ubuntu server, the shell can find exactly 2,977 commands you could type. On top of that come 61 commands built into Bash itself. Nobody needs even a tenth of them. Day to day, about sixty are enough, and most admins type thirty of those every single day. That is what this Linux commands list is for: it separates the tools you use constantly from the 2,900 programs that just happen to be on your path.

The list is sorted by situation, not alphabetically. First orientation and navigation, then files, then searching text, then permissions, processes, disk space, networking and packages. Every command comes with an example you can copy. And because a list alone does not help much, we tested the spots where beginners regularly lose data: on 1 November 2026 on Ubuntu 24.04.5 LTS with Bash 5.2, GNU coreutils 9.4, findutils 4.9 and rsync 3.2.7. Seven of those tests produced a result you will not find in a normal command list.

If you are still deciding which system to use, read Best Linux for beginners first. Almost every command here works the same on Ubuntu, Debian, Fedora and Arch. Where it does not, we say so.

If you would rather watch the basics once: SuperUser Tech walks through the essential terminal commands in a calm beginner guide (August 2026). The video is for following along, this list is for looking things up.

The Linux commands list at a glance

If you only need the table, here it is. Everything else follows below.

SituationCommandWhat it does
Where am I?pwdShow the current directory
What is here?ls -lahFiles with size, permissions, hidden files
Change directorycd /var/logJump into a directory
Go backcd -Return to the previous directory
Create directorymkdir -p a/b/cCreate a directory including parents
Create filetouch file.txtCreate an empty file or update its timestamp
Copycp -a source targetCopy keeping permissions and timestamps
Move/renamemv -i old newMove, ask before overwriting
Deleterm -i fileDelete a file, with confirmation
Delete directoryrm -r dirDelete a directory and its contents
Read a fileless filePage through a file
Start/endhead -n 20, tail -n 50First or last lines
Follow a logtail -F /var/log/syslogNew lines live, survives log rotation
Search textgrep -rn "error" .Recursive search with line numbers
Find filesfind . -name "*.log"Find files by name, age, size
Countwc -l fileCount lines
Sortsort | uniq -cSort and count duplicates
Change permissionschmod 640 fileSet read/write/execute permissions
Change ownerchown user:group fileSet owner and group
As rootsudo commandRun a command with admin rights
Processesps aux, htopShow running processes
Stop a processkill PIDEnd a process politely
Disk spacedf -hUsage per file system
What eats space?du -sh *Size per directory
Memoryfree -hRAM and swap
IP addressesip aNetwork interfaces and addresses
Open portsss -tlnpWhich service listens on which port
Test a websitecurl -I https://…Fetch HTTP headers
Check DNSdig getmind.ioQuery name resolution
Log in remotelyssh user@serverLog in to another machine
Syncrsync -a source/ target/Copy directories efficiently
Archivetar czf backup.tgz dirPack and compress a directory
Packagesapt update && apt upgradeUpdate the system (Debian/Ubuntu)
Servicessystemctl status nginxCheck, start, stop a service
Logsjournalctl -u nginx -fA service’s logs, live
Helpman command, command --helpManual and short help

Tree of folders branching from a single root, with a location marker on one folder and a dotted path between two folders

Before you start: terminal, shell and help

A terminal is the window you type into. The shell is the program inside it that understands and runs your input. On almost every system that is Bash; on macOS and some desktops it is zsh. For every command in this list, the difference does not matter.

On Ubuntu you open a terminal with Ctrl + Alt + T. On a server you land directly in the shell after logging in via SSH. How that works is explained in What is SSH?.

The three most important commands are the ones you use to look up all the others:

man ls          # the full manual for ls (quit with q)
ls --help       # the short version right in the terminal
type ll         # what is behind a command?

type is underrated. On our server, type ll answers “ll is aliased to ls -alF”. So ll is not a program at all, it is a shortcut Ubuntu sets up in .bashrc. On Fedora or inside a Docker container, ll often does not exist, and people are puzzled. Even ls itself is an alias for ls --color=auto on our machine. And type cd says “cd is a shell builtin”: cd is not a program but part of Bash. That is why there is no /usr/bin/cd file, and why man cd has no entry on many systems.

Four keyboard shortcuts save more time than any command:

KeyEffect
TabComplete commands and file names; press twice to see all options
Up arrowPrevious command
Ctrl + RSearch your command history
Ctrl + CCancel the running command

Ctrl + C also answers the most common panic question: “How do I get out of here?” In less and man it is the q key, in vim it is Esc followed by :q!.

Linux has no drive letters. Everything hangs off a single root directory /. Your files live under /home/yourname, configuration under /etc, logs under /var/log, programs under /usr/bin.

pwd: where am I?

pwd
# /home/fabian/projects

ls: what is here?

ls              # names only
ls -l           # long list with permissions, owner, size, date
ls -lah         # plus hidden files and readable sizes (4.0K, 12M)
ls -lt          # sorted by modification time, newest first
ls -lS          # sorted by size

A small test that surprises many people: we created a directory with a file app and a file .env. ls shows one file, ls -A shows two. Files whose names start with a dot are hidden on Linux. That covers exactly the files that matter most: .env with passwords, .git, .ssh, .htaccess. Anyone who checks a directory with ls and says “it’s empty” is often wrong. On servers, always add -a or -A.

cd: change directory

cd /var/log     # absolute path, starts with /
cd projects     # relative path, from the current directory
cd ..           # one level up
cd ~            # to your home directory (plain cd does the same)
cd -            # back to the previous directory

cd - is the command almost no beginner knows and every admin uses constantly: jumping back and forth between two directories without typing the path again.

Files and directories: create, copy, move, delete

mkdir and touch

mkdir backup                    # one directory
mkdir -p project/src/components # including all parent directories
touch notes.txt                 # create an empty file

mkdir -p does not complain if the directory already exists. That is why it appears in almost every script.

cp: copying, and the trap on the second run

cp file.txt copy.txt
cp -r dir target                # copy a directory recursively
cp -a dir target                # recursively AND keep permissions, owner, timestamps

We measured two things. First: a file with permissions 600 and a date of 1 January 2020, copied with plain cp, gets today’s date. With cp -a, 1 January 2020 is preserved. For backups, that is the difference between “I know how old this file is” and “every file is from today”. Always copy backups with -a.

Second, and this is the real trap: running the same cp -r src target twice in a row gives two different results. The first time, target does not exist yet, so src becomes target and its contents land directly in target/. The second time, target already exists, so src lands inside it as a subdirectory. Our test directory ended up containing everything twice: once as target/a/x and once as target/src/a/x. A script that “just copies every night” builds itself a nested copy from the second night on. If you want to be safe, spell out the contents (cp -a src/. target/) or use rsync instead.

mv: moving and renaming without asking

mv old.txt new.txt              # rename
mv file.txt /tmp/               # move
mv -i file.txt target/          # ask before overwriting
mv -n file.txt target/          # never overwrite

Our test: file a.txt containing “old”, file b.txt containing “new”, then mv b.txt a.txt. Result: no warning, no question, a.txt now contains “new”. The old content is gone, and there is no trash can. With mv -n the target stayed untouched, and coreutils 9.4 reported “not replacing ‘c’” with exit code 1. For manual work, an alias alias mv='mv -i' in your .bashrc is worth it.

rm: deleting, for good

rm file.txt
rm -i *.log                     # ask for every file
rm -r dir                       # directory with contents
rm -rf dir                      # no questions, no error messages

rm has no trash can. What is gone is gone. And -f has a side effect that is rarely mentioned: it suppresses not just the questions but also the error when the file does not exist at all. “Deleted” and “I mistyped the name” look identical afterwards. If your script deletes things, check afterwards that the file is really gone instead of trusting the silence.

The most dangerous case is in the “Dangerous commands” section further down.

ln -s /var/www/site/current current   # symbolic link
ln -sr dir1/target dir2/link          # relative, computed correctly

A classic from our test: ln -s dir1/target dir2/link creates a link that points nowhere. The path inside the link is read relative to the link’s directory, not relative to your current directory. cat dir2/link reported “No such file or directory”. With ln -sr, ln computes the correct relative path itself, and the link worked immediately. Alternatively, always use absolute paths.

Reading files and searching text

Several stations in a row connected by transparent pipes, with small data blocks flowing through filter, sorting and counting stations

cat, less, head, tail

cat short.txt                   # print the whole file
less long.log                   # page through, search with /, quit with q
head -n 20 file                 # first 20 lines
tail -n 50 file                 # last 50 lines
tail -n +3 file                 # from line 3 to the end
tail -F /var/log/nginx/error.log  # follow live

tail -f vs. tail -F: the log rotation test

Almost every guide says “use tail -f to follow a log”. On servers it is often the wrong command. Logs are rotated regularly: the old file is renamed (app.log → app.log.1) and a new app.log begins.

We reproduced it. A file with the line “l1”, start both variants, rename the file, create a new file with “l2”, append “l3”. Result:

  • tail -f showed only l1 and nothing after that. It keeps hanging on the renamed old file and waits there forever.
  • tail -F showed l1, l2 and l3. It notices that a new file now sits under the name and follows it.

If you watch for an error overnight and see “no new messages” in the morning, with -f that may just be the midnight rotation. Use -F. For systemd services, journalctl -u service -f is the better choice anyway.

grep: finding text

grep "error" app.log                  # lines containing "error"
grep -i "error" app.log               # case-insensitive
grep -rn "PermitRootLogin" /etc       # recursive, with file name and line number
grep -v "DEBUG" app.log               # all lines WITHOUT DEBUG
grep -c "error" app.log               # number of matching LINES
grep -o "error" app.log | wc -l       # number of MATCHES
grep -E "error|warn" app.log          # multiple patterns

The difference between those two counts is a classic source of wrong numbers in reports. Our test file had three lines: “error error”, “ok”, “error”. grep -c says 2, because two lines match. grep -o … | wc -l says 3, because the word appears three times. If you want to know “how often did the error happen” and use -c, you undercount as soon as one log line contains the pattern more than once.

By the way, searching for PermitRootLogin across all of /etc took 0.3 seconds on our server and found 5 files. If you search code a lot, look at rg (ripgrep). It is faster, respects .gitignore automatically, and was already installed on our server.

Pipes: chaining commands

The real trick of the command line is the | character. It passes one command’s output to the next:

# The 10 IP addresses with the most hits in the Nginx log
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10

# How many PHP files are in the project?
find . -name "*.php" | wc -l

sort, uniq -c, wc -l, cut, awk and sed are the building blocks. uniq only removes adjacent duplicates, which is why sort almost always comes before it.

Redirection: >, >> and the empty file

command > file.txt      # output to a file, OVERWRITES
command >> file.txt     # append output
command 2> errors.txt   # errors only
command > all.txt 2>&1  # output and errors together
command > /dev/null     # throw output away

This is one of the nastiest traps in the shell. We created a file with content and then ran sort file > file, meaning “sort the file and write the result back”. Afterwards the file was 0 bytes. The content was gone, with no error message.

The reason: the shell sets up the redirection before sort even starts. > file empties the file immediately. When sort reads afterwards, it finds an empty file. This applies to every command, not just sort. The correct way is to write to a new file and rename it (sort file > file.new && mv file.new file), or use sort’s built-in option sort -o file file. For sed there is sed -i.

Finding files: find and the -mtime misunderstanding

find /var/log -name "*.log"              # by name
find . -type d -name node_modules        # directories only
find / -size +500M 2>/dev/null           # files over 500 MB
find /tmp -mtime +7                      # older than 7 days (see below!)
find . -name "*.tmp" -delete             # delete what was found
find . -name "*.sh" -exec chmod +x {} +  # run a command on every match

What -mtime +1 really means

We created five files that were 12, 30, 47, 49 and 72 hours old. Then:

CommandFoundWhat you would expect
find -mtime +149 h, 72 h“older than 1 day” → 30 h, 47 h, 49 h, 72 h
find -mtime 130 h, 47 h“exactly 1 day”
find -mmin +144030 h, 47 h, 49 h, 72 h“older than 1440 minutes”

With -mtime, find counts in whole days and throws the remainder away. A file that is 47 hours old counts as “1 day”. +1 means “more than 1 whole day”, so in practice at least 48 hours. A cleanup script with “delete everything older than 7 days” (-mtime +7) therefore only deletes from 8 days on. That is usually harmless, but for backup rotations or deadlines it can matter. If you need precision, use -mmin.

-delete belongs at the end

The order in find is not a formality. In a test directory we ran find fd -delete -name '*.log', accidentally putting -delete before the filter. Result: the entire directory was gone, not just the log file. find evaluates expressions from left to right. -delete comes first and deletes every entry before -name is even checked. No error, no warning.

Our rule: run the find command without -delete first and look at the list. Then append -delete at the end. Never before.

Permissions and users: chmod, chown, sudo

chmod 640 config.php            # owner read/write, group read, others nothing
chmod u+x script.sh             # owner may execute
chmod -R g-w dir                # group may no longer write anywhere
chown www-data:www-data file    # owner and group
sudo command                    # run as root
sudo -i                         # open a root shell
whoami                          # who am I right now?
id                              # user and groups

The numbers in chmod are three digits for owner, group and everyone else. Read is 4, write 2, execute 1. So 6 is read + write, 7 is everything. Our test: chmod 640 gave -rw-r-----. Then chmod u+x,g-r gave -rwx------, which is 700. The letter form changes only what you name; the number form sets everything anew.

chmod -R 777 is the answer you read most often in forums when something “doesn’t work because of permissions”. In our small test directory, a single command made 53 files and directories writable by everyone. On a web server that means any process, including a hijacked plugin, may write there. Find out which user needs to write, and give exactly that user the rights.

The sudo trap with redirection

sudo echo "x" > /etc/file         # fails: Permission denied
echo "x" | sudo tee /etc/file     # works

We checked this as a normal user: “Permission denied”, the file was not created. The reason is the same as with sort > file: the > redirect is handled by your own shell before sudo starts. sudo only applies to echo, not to writing the file. tee, on the other hand, writes the file itself, and it runs with sudo rights.

Processes and services

Server rack with a transparent side showing many small gears as running processes, a memory gauge, and network cables leading to a globe

ps aux                           # all processes
ps aux | grep "[n]ginx"          # targeted search (bracket trick below)
pgrep -a nginx                   # simpler: processes by name
top                              # live overview, q to quit
htop                             # the same, more colorful and easier to use
kill 1234                        # end a process politely (SIGTERM)
kill -9 1234                     # kill a process hard (SIGKILL)
pkill -f "python worker.py"      # end by command line

The bracket trick: ps aux | grep nginx always finds the grep process itself as well. In our test, ps aux | grep -c sshd counted 4 hits, pgrep -c sshd only 2. If you write the pattern as [s]shd, it no longer matches its own command line. pgrep is simpler still.

kill vs. kill -9: the cleanup test

We started a small script that writes a file “cleaned up” when it is terminated, the way a service deletes temporary files or saves data on shutdown. With kill (signal TERM), the file was written. With kill -9, it was not written; the script was simply gone, and its child process kept running orphaned until we ended it ourselves.

kill -9 is not a “stronger kill”, it is a “kill without cleanup”. Databases, services with open files and scripts with lock files leave debris behind. Use kill first, wait a few seconds, and only if nothing happens use -9.

systemctl and journalctl

systemctl status nginx           # is it running? last log lines
sudo systemctl restart nginx     # restart
sudo systemctl reload nginx      # reload config without interruption
sudo systemctl enable --now app  # start at boot and start now
systemctl --failed               # all crashed services
journalctl -u nginx -f           # a service's logs, live
journalctl -u nginx --since "1 hour ago"
journalctl -p err -b             # errors only since the last boot

How to create your own service is shown in Create a systemd service. For recurring tasks there are cron jobs.

Disk space and system

df -h                            # usage per file system
du -sh *                         # size of each entry in the current directory
du -sh /var/log                  # size of one directory
du -h --max-depth=1 / 2>/dev/null | sort -h   # biggest directories under /
free -h                          # memory
uptime                           # uptime and load
uname -r                         # kernel version
cat /etc/os-release              # which distribution?
lsblk                            # disks and partitions

Why df and du disagree

A test that shows why “disk full but I can’t find anything” is so common: we created a 200 MB file, a program opened it, and then we deleted it with rm. du showed 64 KB for the directory afterwards. But the space was not free, because the file had only disappeared from the directory. As long as a process holds it open, the 200 MB stay allocated. lsof +L1 found it instantly: size 209,715,200 bytes, status “(deleted)”, held by exactly that one process.

In practice this happens when you delete a huge log file while the service is still writing to it. df keeps reporting “full”, du finds nothing. The fix is to restart the service, or not to delete the file but to empty it (truncate -s 0 file).

free and the “missing” RAM

On our server with 23 GB of RAM, free -m showed only 1.5 GB “free” but 17.3 GB “available”. That is not a memory problem. Linux uses free RAM as a cache for files (16 GB here) and releases it immediately when a program needs memory. The number to watch is “available”, not “free”. More on this in How much RAM does a server need?.

Our journal took 820 MB (journalctl --disk-usage), the whole /var/log directory 1.4 GB. When the disk fills up, logs and Docker images are the first suspects.

Networking

ip a                             # addresses of all interfaces
ip r                             # routing, default gateway
ss -tlnp                         # listening TCP ports with process
ping -c 4 getmind.io             # reachable?
curl -I https://getmind.io       # HTTP status and headers
curl -s https://api.example.com | jq .   # fetch and pretty-print JSON
wget https://example.com/file.zip        # download a file
dig getmind.io +short            # DNS resolution
dig MX getmind.io                # a domain's mail servers
ssh user@server                  # remote login
scp file.txt user@server:/tmp/   # copy a file

Many guides still list ifconfig and netstat. Both were installed on our server, but they are often missing on fresh minimal Ubuntu and Debian installs. The modern successors are ip and ss, and they are available everywhere. How DNS works is explained in What is DNS?, and for SSH keys see Generate an SSH key.

rsync and the trailing slash

rsync -a source/ target/         # CONTENTS of source into target
rsync -a source target/          # DIRECTORY source into target
rsync -avz --delete source/ user@server:/backup/   # mirror, including deletions
rsync -an --delete source/ target/ # dry run: only shows what would happen

A single slash decides the result with rsync. Our test with the same source: rsync -a src dst1/ produced dst1/src/a/x, rsync -a src/ dst2/ produced dst2/a/x. One has an extra directory level. Combined with --delete this can be dangerous, because --delete removes everything in the target that is missing from the source. Get the path wrong and you mirror an empty or wrong source onto a full target. So always test with -n (dry run) first. Our own deploys work exactly like this: rsync -a --delete dist/ /var/www/…, with the slash, and only after a successful build.

Archives and packages

tar czf backup.tgz dir/          # pack and compress with gzip
tar xzf backup.tgz               # extract
tar tzf backup.tgz               # list contents without extracting
zip -r archive.zip dir/          # ZIP (if installed)
unzip archive.zip

# Debian / Ubuntu
sudo apt update                  # refresh package lists
sudo apt upgrade                 # upgrade installed packages
sudo apt install htop            # install a package
apt search ncdu                  # search for a package

# Fedora / RHEL
sudo dnf upgrade
sudo dnf install htop

With absolute paths, GNU tar 1.35 reported: “Removing leading /' from member names". The archive contained tmp/lbl/t1instead of/tmp/lbl/t1. That is deliberate: when extracting, everything lands relative to the current directory and does not accidentally overwrite system files. Still, look inside an archive with tar tzf` before extracting it. How to build backups properly is covered in the 3-2-1 backup strategy.

Not everything is installed everywhere. Our server was missing tree, ncdu, locate and fd. Present were htop, jq, rg, dig, curl and wget. If a command from a guide says “command not found”, it is usually just one apt install away.

A good complement: SysTelligence (September 2026) shows the modern successors of classic commands, such as ip instead of ifconfig, ss instead of netstat, btop, duf and fd.

Dangerous commands and how to defuse them

Large red emergency button under a transparent safety cover next to a terminal window, with a trash bin into which files are falling

Most data loss on the command line does not come from exotic commands but from harmless commands with one small mistake. We compiled this list from the tests above.

rm -rf with an empty variable

rm -rf "$DIR/"*

If $DIR is empty because someone made a typo or a config value is missing, this becomes rm -rf /*. We obviously did not run that; we only counted what it would hit: 29 entries directly under /, meaning the whole system. The fix costs one line:

set -u                       # abort on unset variables
rm -rf "${DIR:?}/"*          # abort if DIR is empty

With set -u, Bash aborted immediately with “unbound variable” in our test. Every shell script that deletes things should start with set -euo pipefail.

The other traps at a glance

CommandWhat happensHow to defuse it
sort file > filefile is empty afterwardssort -o file file or temp file + mv
mv new oldoverwrites old without askingmv -i or mv -n
find … -delete -name xdeletes everything, not just x-delete always last, test without it first
rsync --delete source targetwrong slash → wrong syncrsync -an first
chmod -R 777everything writable by everyonetargeted owner + 640/750
kill -9no cleanup, debris remainskill first, then wait
tail -f with log rotationstops showing new linestail -F
dd if=… of=/dev/sdXwrong disk → everything gonecheck lsblk, read it twice
curl … | shforeign code runs immediatelydownload, read, then run

What all these cases have in common: none of them prints an error. The command runs, reports success, and you only notice the problem later. The only defense against silent failures is habit: dry runs, confirmation flags, and a backup you can actually restore.

How to remember the commands

Nobody memorizes sixty commands. What works is a small routine:

  1. Start with ten commands: pwd, ls, cd, cp, mv, rm, cat, less, grep, sudo. They get you through the first week.
  2. Aliases for your own habits in ~/.bashrc, for example alias ll='ls -lah' and alias mv='mv -i'. Then run source ~/.bashrc.
  3. Ctrl + R instead of retyping. Once you have typed a command correctly, you can find it again in seconds.
  4. Read --help for every new command, rather than just copying the forum example. The one option you need is almost always there.
  5. Practice in a test environment. A virtual machine or a Docker container (docker run -it ubuntu bash) is ready in seconds and is allowed to break. See What is Docker?.

If you work with Git, you will find the matching commands in our Git commands list. And when your first own server comes up, Linux server setup is the next step.

Conclusion: which Linux commands do you really need?

Of the roughly 3,000 commands on a normal Linux server, you need ten at the start and maybe sixty after a year. More important than the number is knowing the quirks of the most common ones. Our tests showed that the most dangerous situations produce no error message: mv overwrites silently, > file empties the file before it is read, find -delete in the wrong place deletes everything, tail -f loses track after log rotation, and one slash in rsync decides the directory structure.

If you take only three habits from this Linux commands list, make it these: test without -delete or --delete first, use -i with mv and rm, and put set -euo pipefail in every script. That defuses most of the mistakes we found in fifteen minutes of testing.

Frequently asked questions about the Linux commands list

Which Linux commands should beginners know?

Ten are enough to start: pwd, ls, cd, mkdir, cp, mv, rm, cat/less, grep and sudo. Add man and --help for looking things up, and Ctrl + C for cancelling. If you look after a server, you will soon also need df, du, free, systemctl, journalctl, ss and ssh.

How many Linux commands are there?

There is no fixed number, because every installed program is a command. On our Ubuntu 24.04 server, compgen -c found 2,977 commands, plus 61 Bash builtins. /usr/bin held 2,247 programs, /usr/sbin 479. A fresh minimal system has far fewer.

How can I list all available commands?

compgen -c | sort -u lists everything Bash can run, including aliases and functions. Pressing Tab twice on an empty line shows the same interactively. ls /usr/bin shows only installed programs. To search by purpose, use apropos keyword, for example apropos compress.

What is the difference between Linux commands and the Windows command prompt?

The ideas are similar, the names are not. ls corresponds to dir, cp to copy, mv to move, rm to del, cat to type, clear to cls. Linux is case-sensitive, uses / instead of \ and has no drive letters. In PowerShell, some Linux names like ls and cat work as aliases.

How do I cancel a command?

With Ctrl + C. In programs like less, man and top, quit with q. In vim, press Esc and type :q!. If a program does not respond at all, find it in a second terminal with pgrep -a name and end it with kill PID.

What exactly does sudo do?

sudo runs a single command with administrator rights after you enter your own password. Important: it applies only to the command itself, not to > redirects. That is why sudo echo x > /etc/file fails. The correct form is echo x | sudo tee /etc/file.

What is the most dangerous Linux command?

rm -rf / is the famous one, but modern systems refuse exactly that form without --no-preserve-root. More dangerous is rm -rf "$VAR/"* with an empty variable, because it looks like a harmless cleanup command and still hits the whole system. Similarly dangerous: dd to the wrong disk and chmod -R 777 on a web server.

How do I find out what a command does before running it?

man command and command --help explain the options. type command shows whether it is an alias, a function or a program. Many destructive commands have a dry run: rsync -n, find without -delete, apt -s. Try commands from the internet in a test environment first.

Why does df show something different from du?

df measures what the file system reports as used; du adds up the sizes of the files it finds in directories. If a process still holds a deleted file open, df counts it and du does not. In our test that was 200 MB, which lsof +L1 showed instantly. Restarting the service frees the space.

Is there a Linux commands list as a PDF?

We do not offer a separate PDF. You can save this page as a PDF in your browser with Ctrl + P; the table at the top fits on one page. Honestly, a cheat sheet helps less than --help, man and Ctrl + R, because your own command history contains exactly the commands you actually use.

Do these commands work on a Mac too?

Mostly yes, macOS is a Unix. But many tools there are the BSD versions with different options. sed -i, for example, needs an extra empty argument on macOS (sed -i '' …), find lacks some GNU options, and ip, ss, systemctl and apt do not exist at all. If you want the GNU versions, install them via Homebrew with brew install coreutils findutils.