Essential Commands
Navigation, file operations, text processing, piping, redirection, and process management.
Navigation
Three commands account for most of how you move around a filesystem from the shell:
$ pwd
/home/deploy/app
pwd (print working directory) shows exactly where you are — useful before running anything destructive.
$ cd storage/logs # relative path, from wherever you currently are
$ cd /var/www/app # absolute path, always starts from /
$ cd .. # up one directory
$ cd ~ # your home directory
$ cd - # jump back to the previous directory
ls lists directory contents, and its flags are used constantly:
$ ls -la
drwxr-xr-x 5 deploy deploy 4096 Aug 20 09:12 .
drwxr-xr-x 3 deploy deploy 4096 Aug 18 14:02 ..
-rw-r--r-- 1 deploy deploy 1204 Aug 20 09:14 .env
drwxr-xr-x 4 deploy deploy 4096 Aug 20 09:12 storage
-l gives the long listing (permissions, owner, size, date), and -a includes hidden files (anything starting with ., like .env or .git). ls -lh adds human-readable sizes (1.2K instead of 1204).
File operations
# Copy a file
$ cp app.log app.log.bak
# Copy a directory and everything inside it
$ cp -r storage/ storage-backup/
# Move — also how you rename a file, since there's no separate "rename" command
$ mv app.log.bak backups/app-2026-08-20.log
# Remove a file
$ rm app.log.bak
# Remove a directory and its contents (be careful — no trash/recycle bin)
$ rm -rf old-release/
# Create a directory (-p also creates any missing parent directories)
$ mkdir -p releases/2026-08-20/storage
rm -rf deserves real respect: there's no undo. It's worth typing the path with ls first to confirm exactly what you're about to delete before re-running the same path with rm -rf.
Text processing
Most day-to-day Linux work is reading, filtering, and searching text — logs, configs, source code — so these commands are used constantly:
# Print an entire file to the terminal
$ cat app.log
# Page through a file one screen at a time (q to quit, / to search)
$ less app.log
# First 10 lines (default), or specify a count
$ head -n 20 app.log
# Last 10 lines — and -f "follows" the file, printing new lines as they're written
$ tail -f /var/log/nginx/access.log
# Search for a pattern in a file
$ grep "ERROR" app.log
# Case-insensitive, recursive search through a whole directory tree
$ grep -ri "timeout" /var/log/
tail -f is one of the most-used commands in the entire tutorial: it's how you watch a log file live while reproducing a bug or deploying a change.
grep supports full regular expressions, and a few flags come up constantly:
$ grep -n "function login" app.php # -n: show line numbers
$ grep -v "DEBUG" app.log # -v: invert match (lines NOT containing DEBUG)
$ grep -c "ERROR" app.log # -c: count matching lines instead of printing them
Piping and redirection
The shell's real power comes from connecting simple commands together rather than needing one command to do everything.
Piping (|) sends one command's output directly into another command's input:
$ ps aux | grep node
$ cat access.log | grep "500" | wc -l
The second example chains three commands: print the file, keep only lines containing "500", then count the remaining lines (wc -l counts lines). Each command does one small job, and piping composes them.
Redirection sends output to a file instead of the terminal:
$ echo "deployed at $(date)" > deploy.log # > overwrites the file
$ echo "another entry" >> deploy.log # >> appends to the file
$ grep "ERROR" app.log 2> errors-only.log # 2> redirects stderr specifically
$ command > output.log 2>&1 # redirect both stdout and stderr to the same file
> and >> are easy to mix up: > destroys and replaces the file's existing content, >> adds to the end of it. Redirecting into the wrong one (> when you meant >>) is a classic way to accidentally wipe out a log file.
Process management
# Snapshot of every running process, in a user-friendly format
$ ps aux
# Live, auto-refreshing view of CPU/memory usage per process (q to quit)
$ top
# Find a specific process by name
$ ps aux | grep nginx
$ ps aux | grep nginx
deploy 12045 0.0 0.4 55120 8320 ? Ss 09:00 0:00 nginx: worker process
The columns from ps aux that matter most: PID (process ID — you'll need this to kill it), %CPU, %MEM, and COMMAND.
# Ask a process to shut down gracefully (SIGTERM)
$ kill 12045
# Force-kill a process that won't respond (SIGKILL) — a last resort
$ kill -9 12045
# Kill by process name instead of PID
$ pkill -f "node server.js"
kill doesn't actually mean "terminate" by default — it sends a signal, and the target process decides how to respond. Plain kill sends SIGTERM ("please shut down"), which well-behaved programs catch to clean up (close database connections, finish in-flight requests) before exiting. kill -9 sends SIGKILL, which the kernel enforces immediately with no chance for the process to react — useful only when a process is truly stuck.
Common mistakes
- Running
rm -rfwithout double-checking the path withlsfirst — there is no trash can to recover from a mistake. - Using
>when you meant>>and unintentionally wiping out an existing log or config file. - Reaching for
kill -9as a first resort instead of a last one — it gives the process no chance to release locks, flush buffers, or close connections cleanly. - Forgetting
-rwhen copying or removing a directory (cp/rmoperate on files by default; directories need the recursive flag).
Interview questions
Q: What's the difference between piping and redirection?
Piping (|) connects one command's standard output directly to another command's standard input, letting you chain multiple programs together. Redirection (>, >>) sends a command's output to a file instead of the terminal — > overwrites the file, >> appends to it.
Q: How would you find out what's listening on a specific port?
sudo lsof -i :8080 or sudo ss -tulpn | grep 8080 both show which process is bound to that port, including its PID — useful when a service fails to start because "address already in use."
Q: What's the practical difference between kill and kill -9?
Plain kill sends SIGTERM, a request that a well-behaved process can catch to shut down gracefully (closing connections, flushing writes). kill -9 sends SIGKILL, which the kernel terminates the process with immediately, with no opportunity for cleanup — it should only be used when a process is unresponsive to SIGTERM.
Q: How do you view a log file's new lines as they're written, without re-running a command repeatedly?
tail -f filename keeps the file open and prints new lines as they're appended — the standard way to watch a log live while reproducing an issue or during a deployment.