Linux — a learning library¶
The Linux shell, measured — and what changes on a Mac, in zsh and in fish. One idea per page. Every claim on every page is backed by a script that runs, whose output a tool pastes into the page and CI checks again, on Ubuntu and on macOS. Nothing here is quoted from a book and hoped for.
Most Linux books are written on one machine, in one shell. The commands in them look like they will work anywhere, and most will, but not all, and the ones that fail rarely say so. PS1='[\u@\h \W]\$ ' does nothing in fish. ${PIPESTATUS[0]} is silently empty in zsh. grep -P is an error on a Mac. /dev/stdin points into /proc on Linux, and a Mac has no /proc. This library takes the everyday topics of a Linux shell book and runs each example three ways: bash on Linux, the tools a Mac ships with, and zsh and fish. Where the machines agree, a page shows one output; where they disagree, it shows both, and says why.
Start here¶
00 — Start here covers what this library assumes, how a page works, and the Mac-and-fish differences to know first.
The chapters¶
| Chapter | What it covers | |
|---|---|---|
| 01 | Pipelines | | joins stdout to stdin, and what it does not carry: the other stages' exit status, stderr, and variables set on the far side |
| 02 | Redirection | stdin, stdout and stderr as file descriptors 0, 1 and 2: >, >>, 2>&1, <, and /dev/stdin on Linux and on a Mac |
| 03 | tee | One stream into a file and onward down the pipe, and the three things people use it for |
| 04 | grep | GNU grep and the BSD grep a Mac ships: the options that exist in only one, and the patterns that mean different things |
| 05 | tr | Translating, deleting and squeezing characters, and the character classes GNU and BSD tr disagree about |
| 06 | History | Where each shell keeps what you typed, when it writes it, and how to find it again |
| 07 | fzf | A fuzzy filter for any list, and the Ctrl-R history search built on it |
| 08 | The prompt | PS1 in bash, PROMPT in zsh, and a function in fish |
| 10 | Files | The letter ls -l prints before the permissions: seven file types, what opening each one does, and the names test, find, zsh and fish give them. And what a dot means in a path, at the start of a name, and as a command |
| 09 | Resources | The manuals behind each chapter, and the sibling libraries |
Running the examples¶
You need bash, zsh, fish and fzf. A Mac already has bash and zsh; brew install fish fzf adds the other two. Every example is a single script, run from its own folder:
To run all of them and check every recorded output:
The Linux column can be reproduced on a Mac with Docker: docker build -t linux-lib-ubuntu tools/linux_image, then tools/linux_image/run.sh --check. CI pins fzf 0.67.0 and fish 4.3.2 on both machines.
Sibling libraries¶
Same house style, same answer-key contract. Pages here link the page in these that teaches the neighbouring idea:
- C ↗ covers file descriptors,
write(2)andisatty: what a pipe and a redirection are to the program on the other end. - Encodings ↗ covers bytes on a pipe, and a tools chapter ↗ that measures
grep,sed,awk,cut,trandsorton text that is not ASCII. - Python ↗ covers
sys.stdin,sys.stdoutand what a Python program in the middle of a pipeline sees. - Perl ↗ covers the one-liner, which fzf's own Ctrl-R binding uses to prepare your history.
- Ruby text ↗ and Rust ↗: Rust's fuzzy finding page ↗ covers setting up fzf's key bindings.
- Concurrency ↗ covers threads and processes in six languages; its lessons read an exit status such as 134 the way head closes the pipe early reads 141.
- Go ↗ covers goroutines and channels; its pipeline of stages ↗ is a shell pipeline built inside one process.
The one rule¶
No page hand-types what a shell prints. A lesson marks the spot and the runner fills it from a real run, so an example that behaves differently on a new machine breaks the build instead of quietly making a page wrong. See CONTRIBUTING.md.