Foundations
The command line & Unix: the bedrock under everything else.
Once you can open a terminal and move around, this is the next layer: the core commands, how to chain them, how to write a small script, and — the part most guides skip — what "Unix" actually is and how macOS, Linux, and WSL fit together. None of the other tools, or the agents using them, make full sense without it.
This page assumes you've done Getting started — you can open Ghostty, read the prompt, and use cd/ls. Here we widen the toolkit and explain the ground it all stands on.
cp / mv / rm copy / move / removemkdir / touch make folder / filecat / less show / page a filegrep find text in filesfind find files| pipe output → next command> / >> write / append to a filechmod +x make a script runnableman / --help read the manual#A bigger toolkit
Beyond moving around, these are the verbs you'll use constantly. (This setup swaps a few for nicer versions — ls→eza, cat→bat, and grep/find have faster cousins rg/fd on the Shell page — but the classics below are everywhere, so they're worth knowing by name.)
cp src dst | Copy a file (cp -r for a folder) |
mv src dst | Move or rename |
rm file | Remove a file (rm -r a folder). No trash — it's gone. Be careful |
mkdir name | Make a folder (mkdir -p a/b/c makes the whole chain) |
touch file | Create an empty file (or update its timestamp) |
cat file | Print a whole file; less file pages through a long one (q quits) |
head / tail | First / last lines of a file; tail -f follows a growing log live |
grep text | Find lines matching text (across files with grep -r) |
find path | Find files by name, type, age — powerful and a little fiddly |
wc / sort / uniq | Count lines/words · sort lines · collapse duplicates — the classic text toolkit |
ps / kill | List running processes / stop one by its ID (top shows them live) |
chmod / chown | Change a file's permissions / owner |
#The big idea: small tools, piped together
This is the heart of Unix and the reason the command line is so powerful: each tool does one thing, and you connect them. A pipe (|) feeds one command's output into the next; a redirect (>) sends output to a file. Chain a few and you've built something none of them does alone.
$ history | grep git | tail -5 # your last 5 git commands
$ ls -la > listing.txt # write output to a file (overwrite)
$ echo "a note" >> log.txt # append to a file
$ cat names.txt | sort | uniq # sorted, de-duplicated list
a | b | Pipe — send a's output into b as its input |
> file | Send output into a file, replacing it |
>> file | Append output to the end of a file |
< file | Feed a file in as a command's input |
#Permissions & sudo
Every file records who may read, write, and execute it. You'll mostly meet this in two places: making a script executable, and being told "permission denied." chmod +x file grants the run permission. And sudo runs a single command as the all-powerful "root" admin — necessary sometimes, but pause and read any command you're about to sudo, because root can change anything.
rm -rf deletes a folder and everything under it with no undo, and sudo removes the guardrails. They're normal tools — but read them twice before pressing Enter, especially if a path has a variable in it.
#Writing your first script
A shell script is just a file of commands the shell runs top to bottom — the natural next step once you're typing the same sequence repeatedly. Three things make a script: a "shebang" line naming the interpreter, the commands, and the executable permission.
#!/usr/bin/env bash # the shebang: run this with bash
set -euo pipefail # stop on errors + unset vars (good habit)
name="${1:-world}" # first argument, or "world" if none
for i in 1 2 3; do
echo "hello, $name ($i)"
done
$ chmod +x greet.sh # make it runnable (once)
$ ./greet.sh Ada # the ./ means "in this folder"
From there the language grows: variables (name="x", used as $name), conditionals (if), loops (for, while), and functions. The setup's own run_ scripts are real-world examples you can read. Two habits that save hours: start every script with set -euo pipefail, and run it through ShellCheck (linked below) — it catches the classic mistakes before they bite.
#So what is Unix? (and where your Mac fits)
You'll hear "Unix," "Linux," and "macOS" used loosely. Here's the real picture — it explains why some commands you copy from the internet behave differently on a Mac.
One ancestor, two branches
Unix was born at AT&T's Bell Labs in 1969. From it grew two big lineages: the BSD branch (from UC Berkeley) and the System V branch (AT&T's commercial line). Almost every Unix-like system today traces back to one or both.
GNU + Linux = the Linux you hear about
The GNU project (started 1983) rebuilt the Unix tools as free software but lacked a kernel. In 1991 Linus Torvalds released the Linux kernel. GNU's tools + Linux's kernel = a complete free OS, which is why purists call it "GNU/Linux." A distribution ("distro") bundles that into a usable system; the big families:
| Debian → Ubuntu | Ubuntu is built on Debian; both install .deb packages with apt. The common beginner default |
| Fedora → RHEL | Fedora is the fast-moving upstream; Red Hat Enterprise Linux is the stable downstream. Use dnf/rpm |
| Arch | Independent and "rolling release" (always latest); package manager pacman. Minimal, build-it-yourself |
macOS: a real Unix, but not Linux
Your Mac's core is Darwin, built on the XNU kernel — a hybrid of the Mach microkernel and a big helping of BSD. That BSD heritage came to Apple from NeXTSTEP (acquired in 1997). The surprising part: macOS is an officially certified UNIX — it passes The Open Group's UNIX specification, which Linux itself does not. So macOS is genuinely "UNIX," while Linux is "Unix-like." But they share no kernel — macOS is not Linux.
What this means for you, practically
Because macOS ships the BSD versions of the classic tools while most online tutorials assume the GNU (Linux) versions, a few commands take different flags. The ones that actually bite:
sed -i | On a Mac it needs an argument: sed -i '' 's/x/y/' file (the '' = no backup). On Linux it's just sed -i 's/x/y/' file |
date | Mac: date -v-1d for "yesterday"; Linux: date -d "-1 day" |
readlink -f | GNU-only — not on stock macOS |
| Filenames' case | The Mac's default filesystem treats File.txt and file.txt as the same name; Linux treats them as different — a real gotcha when sharing repos |
If you want the Linux behavior, install the GNU versions: brew install coreutils gnu-sed findutils grep. Homebrew names them with a g prefix (gsed, gdate, gls) so they don't shadow the system ones. Also worth knowing: your Mac's default shell has been zsh since macOS Catalina (2019), and the built-in /bin/bash is frozen at an ancient 3.2 — brew install bash if you need a modern one.
#Practice
Compose a pipeline
Run ls -la /usr/bin | wc -l to count the programs in a folder. Then history | grep cd | tail -3. Notice you're building new tools out of small ones — that's the whole game.
Write and run a script
Save the greet.sh above with nvim greet.sh, chmod +x greet.sh, then ./greet.sh yourname. Change the loop, run it again. You just automated something.
Play Bandit
Spend an hour on OverTheWire: Bandit — a game where each level teaches a real command (ls, cat, grep, find, ssh) to unlock the next. The single best hands-on way to get fluent.
#Going deeper
Learn the basics:
- The Linux Command Line (William Shotts) — the best free book for newcomers, first commands through scripting. Free PDF, kept current.
- The Missing Semester (MIT) — free course on the shell, scripting, and tooling; the single best foundation.
- The Linux command line for beginners (Ubuntu) — assumes zero knowledge.
- explainshell.com — paste any command, see every flag explained.
Shell scripting:
- BashGuide (Greg's Wiki) — the canonical "learn bash correctly" tutorial; pair it with BashPitfalls.
- ShellCheck — paste a script and it flags bugs instantly. Run it on everything you write.
- Google Shell Style Guide — sensible conventions, and when not to use a shell script.
- devhints.io Bash cheat sheet — a dense one-page reference.
Practice & drills:
- OverTheWire: Bandit — 34 levels of real command-line problem-solving. Start here.
- cmdchallenge — "do X in one command" browser puzzles.
- Exercism — Bash track — graded exercises with free mentoring.
- SadServers — fix a "broken" Linux server; realistic debugging practice.