Command-Line Notes
A short English companion to the Chinese pages: the handful of rules that explain most shell surprises, plus two lookup tables I keep coming back to. The full notes are in Chinese; these sections are the parts that read better in English.
1. Quoting, in three rules
Nearly every "why did my script do that" question comes down to how the shell split the line into words.
- Single quotes are literal: no expansion at all. You cannot embed a single quote inside them.
- Double quotes are literal except for
$, backticks and\, which still expand. - No quotes means word splitting and globbing. Runs of spaces collapse, and a filename with a space becomes two arguments.
name="two spaces"
printf '%s\n' $name # "two spaces" - collapsed
printf '%s\n' "$name" # "two spaces" - preserved
The practical rule: always quote variable expansions unless you have a specific reason not to. The classic failure is a loop over files that breaks the first time someone uploads my report.txt.
2. Exit codes and strict mode
Zero means success, anything else is a failure. $? holds the status of the previous command, but every command overwrites it — including echo — so capture it immediately.
curl -fsS -o /dev/null http://example.com/health
rc=$?
[ "$rc" -eq 0 ] || echo "health check failed: $rc" >&2
Start non-trivial scripts with:
set -euo pipefail
| Flag | Effect |
|---|---|
-e | Exit when a command fails (with exceptions: conditions, && lists, !). |
-u | Error on an unset variable instead of expanding it to an empty string. |
-o pipefail | A pipeline fails if any stage fails, not just the last one. |
Without pipefail, curl … | head reports success whenever head succeeds, which hides a broken download completely.
3. Pipeline patterns worth memorising
# Count lines by a key
awk '{print $1}' access.log | sort | uniq -c | sort -rn
# Keep the header, filter the rest
awk 'NR == 1 || $3 > 100' data.tsv
# Replace in place (GNU sed; BSD sed needs -i '')
sed -i 's/old/new/g' file
# Walk files safely, including names with spaces
find . -type f -name '*.log' -print0 | xargs -0 gzip
# Fail loudly if a variable is empty
: "${TOKEN:?TOKEN must be set}"
Two habits that prevent most data loss: run find … -print before adding -delete, and never parse ls output — use globs or find.
4. Undoing things in Git
| Situation | Command | What survives |
|---|---|---|
| Edited, not staged | git restore <file> | Nothing — the change is discarded |
| Staged, not committed | git restore --staged <file> | The edit stays in the working tree |
| Committed, not pushed | git commit --amend | Same changes, new commit object |
| Committed, not pushed | git reset --soft HEAD~1 | Changes return to the index |
| Already pushed | git revert <sha> | History unchanged, a new inverse commit is added |
| Anything, within 90 days | git reflog | Recover a lost tip by hash |
Never rewrite a branch other people have pulled. git push --force-with-lease is the least dangerous way to force, because it refuses when the remote has commits you have not seen.
5. HTTP status codes at a glance
| Code | Meaning | When to use it |
|---|---|---|
200 | OK | Successful read or update with a body |
201 | Created | After POST, with a Location header |
204 | No Content | Success with nothing to return |
301 / 308 | Moved permanently | Permanent; browsers cache it for a long time |
302 / 307 | Found / Temporary redirect | Use 307 if the method and body must be preserved |
304 | Not Modified | Answer to a conditional request; no body |
401 | Unauthorized | Missing or invalid credentials |
403 | Forbidden | Authenticated but not allowed |
404 | Not Found | The resource does not exist |
409 | Conflict | Concurrent edit or state clash |
429 | Too Many Requests | Rate limited; include Retry-After |
502 / 504 | Bad Gateway / Gateway Timeout | Upstream returned garbage / did not answer in time |
Returning 200 with an error payload inside the body breaks caching, monitoring and retry logic all at once. Status codes are for infrastructure; business error codes belong in the body.
6. Where to go next
The Chinese pages go into much more detail, with worked examples and platform differences:
- Git 命令速查 — branches, rebase, bisect, common traps
- Shell 文本处理 — grep, sed, awk, a log-analysis walkthrough
- 正则表达式 — dialect differences and catastrophic backtracking
- Markdown 语法 — the parts that render inconsistently
- HTTP 基础 — caching, conditional requests, curl recipes
- 字符编码 — UTF-8 byte structure, mojibake, NFC/NFD