Linux 13 🐧 uniq, head, tail and tee commands
These four commands handle specific parts of file processing: finding duplicates, viewing the start or end of files, and simultaneously displaying and saving output.
Overview
| Command | Purpose | Best For |
|---|---|---|
uniq | Filter duplicate lines | Removing/finding duplicates in sorted files |
head | Show beginning of file | Previewing files |
tail | Show end of file | Viewing recent log entries |
tee | Write to file AND display | Logging while watching output |
The uniq Command
Filters out duplicate lines from a sorted file.
cat data.txt
uniq data.txt
uniq -c data.txt
uniq -d data.txt
uniq -u data.txt
⚠️ Important: uniq only removes adjacent duplicates. Sort the file first!
| Option | Description |
|---|---|
| (none) | Remove adjacent duplicate lines |
-c | Count the number of times each line appears |
-d | Show only duplicate lines |
-u | Show only unique lines |
-i | Ignore case |
-f N | Skip first N fields |
Examples
Sample file:
$ cat data.txt
apple
apple
banana
banana
banana
cherry
cherry
date
Basic uniq (removes adjacent duplicates):
$ uniq data.txt
apple
banana
cherry
date
Count occurrences (-c):
$ uniq -c data.txt
2 apple
3 banana
2 cherry
1 date
Only duplicates (-d):
$ uniq -d data.txt
apple
banana
cherry
Only unique (-u):
$ uniq -u data.txt
date
The uniq + sort Pipeline
This is the classic pattern — sort first, then uniq:
$ cat unsorted.txt
banana
apple
banana
cherry
apple
banana
$ sort unsorted.txt | uniq
apple
banana
cherry
$ sort unsorted.txt | uniq -c
2 apple
3 banana
1 cherry
$ sort unsorted.txt | uniq -c | sort -rn
3 banana
2 apple
1 cherry
Word frequency — a common interview task:
$ cat file.txt | tr ' ' '\n' | sort | uniq -c | sort -rn | head -10
The head Command
Displays the beginning of a file. Default: 10 lines.
head -n 2 data.txt
head -c 3 data.txt
cat data.txt | head -n 2
| Option | Description |
|---|---|
| (none) | Show first 10 lines |
-n N | Show first N lines |
-c N | Show first N bytes |
-q | Quiet (no headers with multiple files) |
-v | Always show headers |
Examples
First 10 lines (default):
$ head data.txt
# Shows first 10 lines
First N lines:
$ head -n 2 data.txt
Line 1
Line 2
$ head -n 5 log.txt
# First 5 lines
First N bytes:
$ head -c 3 data.txt
Lin
$ head -c 10 data.txt
Line 1
Li
Multiple files:
$ head -n 2 file1.txt file2.txt
==> file1.txt <==
Line 1
Line 2
==> file2.txt <==
Alpha
Beta
With pipe:
$ cat data.txt | head -n 2
Line 1
Line 2
$ ls -l | head -n 5
# First 5 lines of directory listing
Negative numbers (GNU extension):
$ head -n -5 data.txt
# Shows all lines EXCEPT the last 5
The tail Command
Displays the end of a file. Default: 10 lines.
tail -n 2 data.txt
cat data.txt | tail -n 2
| Option | Description |
|---|---|
| (none) | Show last 10 lines |
-n N | Show last N lines |
-c N | Show last N bytes |
-f | Follow — show new lines as they’re added |
-F | Follow even if file is rotated |
Examples
Last 10 lines (default):
$ tail data.txt
# Shows last 10 lines
Last N lines:
$ tail -n 2 data.txt
Line 8
Line 9
$ tail -n 5 log.txt
# Last 5 lines
Last N bytes:
$ tail -c 3 data.txt
ine
The -f flag — follow a log in real-time:
$ tail -f /var/log/syslog
# Displays new lines as they appear
# Ctrl+C to stop
Combine with grep for monitoring:
$ tail -f /var/log/syslog | grep "ERROR"
# Only shows new ERROR lines
Multiple files:
$ tail -n 2 file1.txt file2.txt
==> file1.txt <==
Line 8
Line 9
==> file2.txt <==
Gamma
Delta
Starting from line N:
$ tail -n +3 data.txt
# Starts from line 3 and shows the rest
The tee Command
Reads from stdin, writes to stdout AND a file at the same time.
echo "kronos" | tee data2.txt
echo "kronos2" | tee -a data2.txt
echo "kronos2" | tee data2.txt data3.txt
Visual:
┌──────────────────┐
stdin ──│ tee │──stdout──│ Terminal
└───────┴──────────┘
│
└──file──→ File
| Option | Description |
|---|---|
| (none) | Write to stdout and file (overwrite) |
-a | Append to file instead of overwriting |
-i | Ignore interrupt signals |
| Multiple files | Write to all files at once |
Examples
Basic tee:
$ echo "kronos" | tee data2.txt
kronos # ← displayed on terminal
$ cat data2.txt
kronos # ← also saved to file
Append mode (-a):
$ echo "kronos2" | tee -a data2.txt
kronos2
$ cat data2.txt
kronos
kronos2 # ← both lines saved
Write to multiple files:
$ echo "kronos2" | tee data2.txt data3.txt
kronos2
$ cat data2.txt
kronos2
$ cat data3.txt
kronos2 # ← saved to both files
Save AND view command output:
$ ls -la | tee file-list.txt
# Displays listing AND saves to file-list.txt
Log while watching:
$ ./script.sh | tee -a script.log
# See live output AND append to log
Privileged write (sudo tee):
$ echo "127.0.0.1 mysite.local" | sudo tee -a /etc/hosts
# Use tee when you need sudo to write
# (sudo redirect ">" doesn't work as expected)
Complete Example Session
# ============================================
# PART 1: UNIQ
# ============================================
# Create a file with duplicates
$ cat > data.txt << EOF
apple
apple
banana
banana
banana
cherry
cherry
date
EOF
# Remove adjacent duplicates
$ uniq data.txt
apple
banana
cherry
date
# Count occurrences
$ uniq -c data.txt
2 apple
3 banana
2 cherry
1 date
# Only duplicates
$ uniq -d data.txt
apple
banana
cherry
# Only unique
$ uniq -u data.txt
date
# Classic sort | uniq pipeline
$ sort unsorted.txt | uniq -c | sort -rn
# ============================================
# PART 2: HEAD
# ============================================
# First 10 lines (default)
$ head data.txt
# First 2 lines
$ head -n 2 data.txt
apple
apple
# First 3 bytes
$ head -c 3 data.txt
app
# Multiple files
$ head -n 2 file1.txt file2.txt
==> file1.txt <==
...
# With pipe
$ cat data.txt | head -n 2
# ============================================
# PART 3: TAIL
# ============================================
# Last 10 lines (default)
$ tail data.txt
# Last 2 lines
$ tail -n 2 data.txt
cherry
date
# Last 3 bytes
$ tail -c 3 data.txt
ate
# Real-time log monitoring
$ tail -f /var/log/syslog
# Filter followed output
$ tail -f /var/log/syslog | grep "ERROR"
# ============================================
# PART 4: TEE
# ============================================
# Write and display
$ echo "kronos" | tee data2.txt
kronos
# Append
$ echo "kronos2" | tee -a data2.txt
kronos2
# Multiple files
$ echo "kronos2" | tee data2.txt data3.txt
kronos2
# Save command output
$ ls -la | tee file-list.txt
# Using tee with sudo
$ echo "127.0.0.1 myapp.local" | sudo tee -a /etc/hosts
# ============================================
# PART 5: COMBINING THEM
# ============================================
# Top 5 most frequent lines
$ sort file.txt | uniq -c | sort -rn | head -5
# View the beginning and end
$ head -n 5 data.txt && tail -n 5 data.txt
# Watch a log AND save it
$ tail -f /var/log/syslog | tee -a syslog-backup.txt
# Find duplicate IPs in a log
$ grep -oE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" access.log | sort | uniq -c | sort -rn | head -10
# First and last lines of file
$ { head -n 1 file.txt; tail -n 1 file.txt; }
# Save AND display grep results
$ grep "ERROR" log.txt | tee errors.txt | wc -l
# ============================================
# PART 6: PRACTICAL EXAMPLES
# ============================================
# Analyze top visitors
$ awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10
# Watch deployment log with backup
$ tail -f deploy.log | tee -a deploy-backup.txt
# Check first and last entries in a CSV
$ head -n 2 data.csv
$ tail -n 2 data.csv
# Find duplicate filenames
$ ls | sort | uniq -d
# Unique lines only
$ cat file.txt | sort -u
# Recent errors from syslog
$ grep "ERROR" /var/log/syslog | tail -n 20
# Save terminal session
$ script -c "bash" session.log
Quick Reference
uniq Options
| Option | Description |
|---|---|
| (none) | Remove adjacent duplicates |
-c | Count occurrences |
-d | Duplicates only |
-u | Unique only |
-i | Ignore case |
head Options
| Option | Description |
|---|---|
| (none) | First 10 lines |
-n N | First N lines |
-c N | First N bytes |
-n -N | All except last N lines |
tail Options
| Option | Description |
|---|---|
| (none) | Last 10 lines |
-n N | Last N lines |
-c N | Last N bytes |
-f | Follow (real-time) |
-n +N | Start from line N |
tee Options
| Option | Description |
|---|---|
| (none) | Write (overwrite) |
-a | Append |
-i | Ignore interrupts |
file1 file2 | Multiple files |
Best Practices
✅ Do This:
# Always sort before uniq
sort file.txt | uniq
# Use uniq -c for frequency counting
sort file.txt | uniq -c
# Use head to preview before processing
head -n 5 bigfile.txt
# Use tail -f to monitor logs
tail -f /var/log/syslog
# Use tee to see AND save
command | tee output.txt
# Use sudo tee for privileged writes
echo "content" | sudo tee /etc/important.conf
# Combine head and tail to see both ends
head -n 5 file.txt; echo "..."; tail -n 5 file.txt
❌ Don’t Do This:
# Don't use uniq on unsorted files
uniq unsorted.txt # ❌ Only removes ADJACENT duplicates
sort unsorted.txt | uniq # ✅ Correct
# Don't forget the -a flag with tee
echo "line 2" | tee file.txt # ❌ Overwrites!
echo "line 2" | tee -a file.txt # ✅ Appends
# Don't use > with sudo (misleading)
sudo echo "x" > /etc/file # ❌ Redirect runs as user, not root
sudo tee /etc/file <<< "x" # ✅ tee runs as root
# Don't tail -f without a way to stop
tail -f log.txt # Ctrl+C to stop
# (it runs forever, watching the file)
# Don't use uniq for global duplicate removal
sort file.txt | uniq # ✅ Always sort first
Common Pitfalls
| Pitfall | Problem | Solution |
|---|---|---|
uniq on unsorted file | Only adjacent duplicates removed | Use sort | uniq |
tee overwrites | Loses old data | Use -a to append |
sudo > doesn’t work | Redirect runs as user | Use sudo tee |
tail -f on deleted file | Keeps running | Use -F to follow rotations |
head/tail without args | 10 lines default | Add -n N for precision |
| Forgetting to sort | uniq misses duplicates | Always sort first |
Real-World Examples
1. Find most common HTTP status codes
awk '{print $9}' access.log | sort | uniq -c | sort -rn
2. Monitor a log for errors in real time
tail -f /var/log/syslog | grep --line-buffered "ERROR"
3. Save and display a command’s output
find /etc -name "*.conf" 2> /dev/null | tee config-files.txt
4. Preview a large file
# First 5 lines and last 5 lines
head -n 5 huge.log; echo "..."; tail -n 5 huge.log
5. Write to a root-owned file
echo "nameserver 8.8.8.8" | sudo tee -a /etc/resolv.conf
6. Top 10 most frequent words in a file
cat book.txt | tr -s ' ' '\n' | sort | uniq -c | sort -rn | head -10
7. Find duplicate lines across multiple files
cat *.txt | sort | uniq -d
8. Count unique visitors from a log
awk '{print $1}' access.log | sort -u | wc -l
9. Watch a log while saving a copy
tail -f app.log | tee -a app-archive.log
10. Verify package installation order
grep "install " /var/log/dpkg.log | tail -n 20
Visual: Command Output
UNIQ: HEAD: TAIL:
Sort removes duplicates First N lines Last N lines
┌──────────┐ ┌──────────┐
Input: Output: │ Line 1 │ │ Line 18 │
apple │ Line 2 │ │ Line 19 │
apple → apple │ Line 3 │ │ Line 20 │
banana → banana │ ... │ │ ... │
banana → cherry └──────────┘ └──────────┘
cherry → date (head -n 3) (tail -n 3)
cherry
date
TEE:
┌────────────────────┐
stdin ──→ │ tee -a │ ──→ stdout (terminal)
└────────┬───────────┘
│
└──→ file (saved)
Summary
| Command | Purpose | Example |
|---|---|---|
uniq | Filter duplicates | sort file | uniq -c |
head | Show beginning | head -n 5 file.txt |
tail | Show end | tail -f log.txt |
tee | Save and display | cmd | tee -a log.txt |
Key takeaways:
uniqworks on sorted input — alwayssortfirst for real deduplicationuniq -cis your friend for frequency countingheadandtailboth default to 10 lines and support-nand-ctail -fis the go-to way to monitor logs in real timeteelets you see AND save — perfect for loggingtee -aappends instead of overwritingsudo teeis the correct way to write to root-owned files
Remember: These commands are the precision tools of text processing. uniq for duplicates, head/tail for previewing, and tee for logging — combined with sort, grep, and pipes, they let you handle almost any file-processing task. And the most common pattern in the wild? sort | uniq -c | sort -rn | head — the go-to one-liner for “show me the top occurrences of anything”!
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!