📄 Lesson 4.1: Viewing File Contents
Peek, scroll, search, and slice — every way to read files without opening an editor.
🎯 Learning Objectives
- Display entire files with
cat - Scroll through files with
less - Preview the start or end of a file with
headandtail - Search inside files with
grep - Count lines, words, and characters with
wc - Sort, deduplicate, and compare files
- Combine commands with pipes (
|)
Estimated Time: 35 minutes
📑 In This Lesson
cat — Display a File
cat (short for concatenate) dumps the entire contents of a file to your terminal:
# Display a file
cat /etc/hostname
# Display with line numbers
cat -n /etc/hosts
# Display multiple files (concatenated together)
cat file1.txt file2.txt
# Concatenate files into a new file
cat header.txt body.txt footer.txt > full_page.txt
⚠️ When NOT to Use cat
cat dumps the entire file to your terminal at once. For large files (log files, data dumps), your terminal will be flooded with text. Use less instead for anything longer than a screen.
Useful cat Variations
# Show non-printing characters (tabs as ^I, line endings as $)
cat -A file.txt
# Squeeze multiple blank lines into one
cat -s file_with_gaps.txt
# Number only non-blank lines
cat -b file.txt
💡 tac — cat Backwards
Yes, tac is a real command — it prints a file in reverse, last line first. Handy for quickly checking the end of a log file: tac /var/log/syslog | head -20
less — Scroll Through a File
less is an interactive file viewer — it lets you scroll, search, and navigate without loading the entire file into memory:
# Open a file in less
less /var/log/syslog
# Open with line numbers
less -N /etc/services
Navigation Inside less
| Key | Action |
|---|---|
| Space or f | Forward one page |
| b | Back one page |
| ↓ or j | Down one line |
| ↑ or k | Up one line |
| g | Go to the beginning |
| G | Go to the end |
| /pattern | Search forward for "pattern" |
| ?pattern | Search backward for "pattern" |
| n | Next search match |
| N | Previous search match |
| q | Quit |
✅ less Is Your Best Friend
less is the go-to tool for reading files on Linux. It works on huge files without loading them entirely into memory, supports forward and backward searching, and leaves your terminal clean when you quit. The saying goes: "less is more" (it literally replaced the older more command).
🐧 less vs more
more is the older, simpler pager — it only scrolls forward. less can scroll both directions, search, and handle very large files. On modern systems, more is often just an alias for less. Always use less.
head and tail — Start and End
When you only need to see part of a file:
# Show the first 10 lines (default)
head /etc/passwd
# Show the first 5 lines
head -n 5 /etc/passwd
# or shorthand:
head -5 /etc/passwd
# Show the last 10 lines (default)
tail /etc/passwd
# Show the last 20 lines
tail -n 20 /var/log/syslog
# Show everything EXCEPT the first 3 lines
tail -n +4 file.txt
tail -f — Follow a File in Real Time
This is one of the most useful commands for monitoring log files:
# Watch a log file as new lines are added
tail -f /var/log/syslog
# Follow with highlighting (using grep)
tail -f /var/log/syslog | grep --color "error"
# Press Ctrl+C to stop following
💡 tail -f Is Essential
When debugging a server, watching a build, or monitoring a service, tail -f lets you see new log entries the instant they're written. It's one of the most-used commands in system administration and development.
(100 lines)"] --> B["head -5
Lines 1–5"] A --> C["tail -5
Lines 96–100"] A --> D["tail -f
Live updates!"] style B fill:#3b82f6,stroke:#2563eb,color:#fff style C fill:#6366f1,stroke:#4338ca,color:#fff style D fill:#22c55e,stroke:#166534,color:#fff
grep — Search Inside Files
grep (Global Regular Expression Print) searches for a pattern and prints matching lines:
# Search for a word in a file
grep "error" /var/log/syslog
# Case-insensitive search
grep -i "warning" /var/log/syslog
# Show line numbers
grep -n "root" /etc/passwd
# Search recursively in all files in a directory
grep -r "TODO" ~/projects/
# Show lines that do NOT match
grep -v "comment" config.txt
# Count matching lines
grep -c "error" /var/log/syslog
# Show surrounding context (2 lines before and after each match)
grep -B 2 -A 2 "error" /var/log/syslog
💡 Useful grep Combos
# Combine flags: case-insensitive, recursive, with line numbers
grep -rni "fixme" ~/projects/
# Search for whole words only (not partial matches)
grep -w "is" file.txt # matches "is" but not "this" or "island"
# Show only filenames that contain a match
grep -rl "password" /etc/
| Option | Meaning |
|---|---|
-i | Case-insensitive |
-n | Show line numbers |
-r | Recursive (search directories) |
-v | Invert — show non-matching lines |
-c | Count matches only |
-w | Whole words only |
-l | Show only filenames with matches |
-B N | Show N lines before each match |
-A N | Show N lines after each match |
--color | Highlight matches in color |
wc — Count Things
wc (word count) tells you how many lines, words, and characters are in a file:
# Full count: lines, words, characters
wc /etc/passwd
# 45 87 2678 /etc/passwd
# │ │ │
# │ │ └── characters (bytes)
# │ └─────── words
# └──────────── lines
# Count only lines
wc -l /etc/passwd
# 45 /etc/passwd
# Count only words
wc -w essay.txt
# Count multiple files
wc -l *.txt
💡 wc -l Is Everywhere
wc -l is one of the most frequently piped-to commands on Linux. How many processes are running? ps aux | wc -l. How many files match? find . -name "*.js" | wc -l. How many errors in the log? grep "error" log.txt | wc -l.
sort and uniq
sort — Order Lines
# Alphabetical sort
sort names.txt
# Reverse sort
sort -r names.txt
# Numeric sort
sort -n scores.txt
# Sort by a specific column (e.g., 3rd field, separated by :)
sort -t: -k3 -n /etc/passwd
uniq — Remove Consecutive Duplicates
# Remove consecutive duplicate lines (sort first!)
sort colors.txt | uniq
# Count occurrences of each line
sort colors.txt | uniq -c
# Show only the duplicates
sort colors.txt | uniq -d
# Show only unique lines (appear exactly once)
sort colors.txt | uniq -u
⚠️ uniq Only Removes Consecutive Duplicates
uniq compares each line to the one before it. If duplicates aren't adjacent, they won't be removed. That's why you almost always sort first: sort file.txt | uniq.
Pipes — Combining Commands
The pipe (|) takes the output of one command and feeds it as input to the next. This is one of the most powerful ideas in Linux:
produces output"] -->|"pipe |"| B["Command B
filters / transforms"] B -->|"pipe |"| C["Command C
formats / counts"] style A fill:#3b82f6,stroke:#2563eb,color:#fff style B fill:#6366f1,stroke:#4338ca,color:#fff style C fill:#22c55e,stroke:#166534,color:#fff
# Count how many users are on the system
cat /etc/passwd | wc -l
# Find all error lines in a log, sorted, deduplicated
grep "error" /var/log/syslog | sort | uniq
# Top 10 most common words in a file
cat essay.txt | tr ' ' '\n' | sort | uniq -c | sort -rn | head -10
# Find the 5 largest files in a directory
ls -lS /var/log/ | head -6
# Show all running processes, filter for python
ps aux | grep python
# Count how many .html files are in a project
find ~/projects -name "*.html" | wc -l
✅ The Unix Philosophy
Linux commands are designed to do one thing well and to work together via pipes. grep searches, sort sorts, wc counts, head truncates. By chaining them with pipes, you can build powerful data-processing pipelines without writing any code.
💡 Building Pipes Step by Step
Don't try to write a long pipe all at once. Build it one command at a time:
- Run the first command alone and check its output
- Pipe it to the next command and check again
- Keep adding stages until you get the result you want
diff — Comparing Files
When you need to see what's different between two files:
# Basic comparison
diff file1.txt file2.txt
# Side-by-side view
diff -y file1.txt file2.txt
# Unified format (like Git diffs)
diff -u file1.txt file2.txt
# Just check if files differ (no details)
diff -q file1.txt file2.txt
# Compare two directories
diff -r dir1/ dir2/
Reading diff Output
2c2
< old line
---
> new line
5a6
> added line
c = changed, a = added, d = deleted. < is from file 1, > is from file 2.
💡 colordiff for Readability
Install colordiff (sudo apt install colordiff) for color-coded diffs. Use it the same way as diff: colordiff -u file1.txt file2.txt.
Exercises
🏋️ Exercise 1: Explore /etc/passwd
# How many user accounts exist?
wc -l /etc/passwd
# Show only the first 5 entries
head -5 /etc/passwd
# Find your own entry
grep $USER /etc/passwd
# List all shells in use (7th field)
cat /etc/passwd | cut -d: -f7 | sort | uniq -c | sort -rn
💡 What's Happening in That Last Line?
cut -d: -f7 extracts the 7th colon-separated field (the shell). sort groups identical shells together. uniq -c counts each unique shell. sort -rn sorts by count, highest first. This is a classic pipe pattern!
🏋️ Exercise 2: grep Practice
# Create a test file
cat > colors.txt << 'EOF'
Red is warm
Blue is cool
Green is natural
red is also a stop sign
BLUE is the sky
Yellow is bright
orange is citrus
EOF
# Case-insensitive search for "blue"
grep -i "blue" colors.txt
# Lines that do NOT contain "is"
grep -v "is" colors.txt
# Count lines containing "is"
grep -c "is" colors.txt
# Show line numbers
grep -n "is" colors.txt
🏋️ Exercise 3: Pipes Challenge
Using /etc/services, answer these questions with one-liner pipes:
# How many services are defined?
grep -v "^#" /etc/services | grep -v "^$" | wc -l
# How many use TCP?
grep "tcp" /etc/services | wc -l
# What are the first 5 TCP services?
grep "tcp" /etc/services | head -5
🏋️ Exercise 4: diff Practice
# Create two similar files
echo -e "apple\nbanana\ncherry" > fruits1.txt
echo -e "apple\nblueberry\ncherry\ndate" > fruits2.txt
# Compare them
diff fruits1.txt fruits2.txt
# Side-by-side
diff -y fruits1.txt fruits2.txt
# Unified format
diff -u fruits1.txt fruits2.txt
# Clean up
rm fruits1.txt fruits2.txt colors.txt
Knowledge Check
❓ Question 1
Which command is best for viewing a large log file?
❓ Question 2
What does tail -f do?
❓ Question 3
What does the pipe (|) do?
❓ Question 4
Why do you typically sort before uniq?
Quick Reference
| Command | What It Does | Example |
|---|---|---|
cat | Display entire file | cat file.txt |
less | Scroll through a file | less /var/log/syslog |
head -n N | Show first N lines | head -20 file.txt |
tail -n N | Show last N lines | tail -20 file.txt |
tail -f | Follow new lines in real time | tail -f /var/log/syslog |
grep | Search for pattern in files | grep -rni "TODO" src/ |
wc -l | Count lines | wc -l file.txt |
sort | Sort lines | sort -n scores.txt |
uniq | Remove consecutive duplicates | sort data | uniq -c |
diff | Compare two files | diff -u old.txt new.txt |
| | Pipe output to next command | grep err log | wc -l |
Summary
🎉 Key Takeaways
catdumps a file; uselessfor anything bigger than a screenheadandtailshow the start or end;tail -ffollows live updatesgrepis the universal search tool — memorize-rni(recursive, line numbers, case-insensitive)wc -lcounts lines — pipe anything to it for a quick count- Always
sortbeforeuniqbecauseuniqonly catches adjacent duplicates - Pipes (
|) are the glue — chain simple commands into powerful pipelines diffshows what changed between two files;-ugives the most readable output
🍎 On macOS
All the commands in this lesson (cat, less, head, tail, grep, wc, sort, uniq, diff) work on macOS. One subtlety: macOS ships BSD versions of these tools, which occasionally differ from the GNU versions on Linux. For example, macOS grep doesn't support -P (Perl regex). Install GNU versions with brew install coreutils grep if you hit differences.
🚀 What's Next?
Now that you can view files, the next lesson teaches you to edit them — with nano (the friendly editor) and vim (the powerful one).