How to Survive in the Terminal
A practical guide to using a Linux shell without guessing.
The terminal commands that worry me most are the ones I almost understand. A familiar name, an unfamiliar flag, and enough confidence to press Enter can do more damage than complete ignorance.
Shell competence is not a large command vocabulary. It is knowing what interprets a line, what arguments a program receives, and how to verify the result. These examples assume GNU/Linux and a Bourne-style shell such as Bash.
Know what will run, and where
The terminal emulator is the window. The shell reads and expands your command line. A command name may resolve to a builtin, executable, alias, or function. cd is normally a builtin because it must change the current shell; ls is usually an external utility. Ask rather than guess:
command -V cd
command -V lsEvery shell process also has a current working directory. Relative paths start there; absolute paths start at /. The same relative command can therefore address different files in two terminals.
pwd
ls
cd projects/service
pwd. means the current directory and .. its parent. cd with no argument goes to your home directory, while cd - returns to the previous directory and prints it. Use pwd again after changing location instead of relying on a shortened prompt. Quote paths that may contain spaces or characters the shell treats specially:
cd "$HOME/Project Notes"
ls -- "release candidates"Many utilities treat -- as the end of options, preventing a filename such as -draft from becoming a flag. Before acting on a path, inspect it:
file ./artifact
stat ./artifact
head -n 20 app.log
less app.log
grep -n 'ERROR' app.logfile examines content and stat reports metadata. less lets you browse without dumping a large file into the terminal; /text searches and q exits. Search commands should also begin as inspection:
find ./src -type f -name '*.ts' -printThis prints the selection without changing the files. Reading it tells you whether the starting directory and expression mean what you thought.
Predict the arguments and destinations
A pipe connects one command’s standard output to another’s standard input:
journalctl -u my-service --since today | grep 'timeout' | lessRead it left to right: produce logs, retain matching lines, browse them. Errors normally remain on standard error rather than entering the pipe. Redirection changes the destinations:
printf '%s\n' 'ready' > status.txt
printf '%s\n' 'next check' >> status.txt
command-that-may-fail >output.log 2>error.log> creates or truncates the destination before the command runs. >> appends. Ordering matters when combining output and errors:
build >build.log 2>&1
build 2>&1 | tee build.logIn the first command, the shell points output at the file and then points errors at output’s current destination. In the second, both streams enter the pipe to tee.
The shell expands quotes, variables, globs, and substitutions before many programs run. In this command, rm does not receive the text *.log; the shell replaces the glob with matching filenames first:
rm *.logPreview the expansion with a non-destructive command when the selection matters:
printf '<%s>\n' ./*.logThe delimiters make separate arguments visible, including names containing spaces. Quoting changes that handoff. printf '%s\n' "$HOME" gives printf the expanded home path as one argument. printf '%s\n' '$HOME' gives it the literal characters $HOME. Double quotes preserve one argument while allowing variable expansion; single quotes preserve the text literally. When a command surprises you, reconstruct the arguments and redirections before blaming the program.
Treat privilege and deletion as deliberate actions
Permissions describe access, not intent. On a directory, read lists names, write changes entries, and execute permits traversal. Deleting a file therefore depends mainly on its containing directory, not whether the file itself is writable. Inspect the directory when deletion succeeds or fails unexpectedly.
sudo runs a command under another identity according to policy, often as root. It is not “try again harder.” Read the original error first. Adding privilege to a malformed command only increases what it can damage.
rm removes directory entries without promising a recycle bin. GNU rm -r descends recursively, while -f suppresses some prompts and missing-file complaints. I slow down around it: locate myself, inspect the exact target, preview any generated selection, act narrowly, then inspect the parent.
pwd
ls -ld -- ./build-cache
find ./build-cache -maxdepth 1 -print
rm -r -- ./build-cache
ls -ld -- .The preview is useful because the destructive command here targets the same explicit directory, not because find secretly makes rm safe. For an empty directory, rmdir is safer: unexpected contents make it fail. cp, mv, and > can overwrite too, so the same habit applies beyond deletion.
Read locally, then verify
When I forget an option, I start with the documentation installed beside the program:
command --help
man command
apropos 'search description'man reflects the software on the machine. apropos searches the manual database when you know the task but not the command name. For a shell builtin such as cd, Bash provides help cd. This matters when an online example assumes a different shell or utility version. Read the synopsis to see which words are options and operands, then check the description of any flag you plan to use rather than inferring it from a similar command.
My working grammar is locate → inspect → select → act → verify. Learn an option when a real task needs it, predict the arguments and result, and try a disposable or narrow sample. After acting, check the filesystem, output, or service state that was supposed to change. The line is safe only when you know who interprets it, what the program receives, and how you will verify what happened.