Essential Commands

Navigation, file operations, text processing, piping, redirection, and process management.

Three commands account for most of how you move around a filesystem from the shell:

Bash
$ pwd
/home/deploy/app

pwd (print working directory) shows exactly where you are — useful before running anything destructive.

Bash
$ 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:

Bash
$ 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

Bash
# 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:

Bash
# 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:

Bash
$ 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:

Bash
$ 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:

Bash
$ 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

Bash
# 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.

Bash
# 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 -rf without double-checking the path with ls first — 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 -9 as a first resort instead of a last one — it gives the process no chance to release locks, flush buffers, or close connections cleanly.
  • Forgetting -r when copying or removing a directory (cp/rm operate 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.