Skip to content
elephantoo

Viewing files: cat, less, head & tail

Lesson 6 of 31 12 min read

Read files of any size, follow logs live with tail -f, and inspect files with wc, file and stat.


Reading files is a huge part of working on Linux: configuration files, logs, CSVs, scripts, documentation. Different tools suit different jobs. cat for small files, less for big ones, head and tail for the start and end, and tail -f to watch logs live.

Sample files#

Terminal
printf 'apple\nbanana\ncherry\n' > fruits.txt
for i in $(seq 1 20); do echo "2026-10-01 10:00:$(printf %02d $i) INFO request $i served"; done > app.log
echo "2026-10-01 10:00:21 ERROR database timeout" >> app.log

cat: print whole files#

Terminal
cat fruits.txt
cat -n fruits.txt          # number the lines
Output
apple
banana
cherry
     1	apple
     2	banana
     3	cherry

cat (short for concatenate) can join several files, too: cat part1.txt part2.txt > whole.txt. It's perfect for short files. For anything longer than a screen, use less. tac prints a file backwards, last line first.

less: page through anything#

Terminal
less app.log

less opens the file one screen at a time and doesn't load it all into memory, so even multi-gigabyte logs open instantly.

KeyAction
Space / bnext / previous page
↓ ↑ or j kone line down / up
g / Gjump to the start / end
/text then n / Nsearch forwards; next / previous match
?textsearch backwards
&textshow only lines matching text
Ffollow new lines like tail -f (Ctrl+C to stop)
-Stoggle line wrapping (great for wide logs)
qquit

Useful options: less -N shows line numbers, and less +G file starts at the end. man pages are displayed with less, so these keys work there too. You can also pipe any long output into it: ps aux | less.

head and tail: the start and the end#

Terminal
head -n 3 app.log          # first 3 lines (default: 10)
tail -n 2 app.log          # last 2 lines
Output
2026-10-01 10:00:01 INFO request 1 served
2026-10-01 10:00:02 INFO request 2 served
2026-10-01 10:00:03 INFO request 3 served
2026-10-01 10:00:20 INFO request 20 served
2026-10-01 10:00:21 ERROR database timeout

More forms:

Terminal
tail -n +19 app.log        # from line 19 to the end
head -c 9 fruits.txt; echo  # first 9 bytes (echo adds a newline)
Output
2026-10-01 10:00:19 INFO request 19 served
2026-10-01 10:00:20 INFO request 20 served
2026-10-01 10:00:21 ERROR database timeout
apple
ban

tail -f: watch logs live#

This is one of the most-used commands on any server:

Terminal
tail -f /var/log/syslog

-f (follow) keeps the file open and prints new lines as they're written. Press Ctrl+C to stop. Variations:

  • tail -F file keeps following even when the log is rotated (renamed and recreated), which is usually what you want.
  • tail -f app.log | grep ERROR follows only matching lines.
  • tail -f a.log b.log follows several files, with headers.
  • For systemd services, use journalctl -u nginx -f instead (see systemd services).

wc: counting#

Terminal
wc fruits.txt
wc -l app.log
grep -c ERROR app.log      # count matching lines
Output
3  3 20 fruits.txt
21 app.log
1

wc prints lines, words and bytes. -l, -w and -c select one count, and -m counts characters (which differs from bytes for UTF-8 text).

What kind of file is it?#

Before opening an unknown file, check what it is, since cat on a binary file fills your terminal with garbage:

Terminal
file fruits.txt app.log /etc
Output
fruits.txt: ASCII text
app.log:    ASCII text
/etc:       directory

If your terminal does get garbled, type reset and press Enter. To peek inside a binary safely, use strings file | less (printable text only) or xxd file | head (a hex dump).

stat: full details#

Terminal
stat fruits.txt
Output
  File: fruits.txt
  Size: 20        	Blocks: 8          IO Block: 4096   regular file
Device: 8,1	Inode: 1835123     Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/     ada)   Gid: ( 1000/     ada)
Access: 2026-10-01 10:51:02.120000000 +0530
Modify: 2026-10-01 10:51:02.120000000 +0530
Change: 2026-10-01 10:51:02.120000000 +0530
 Birth: 2026-10-01 10:51:02.120000000 +0530

You'll see size, permissions (in both octal and symbolic form), owner, inode number and timestamps. Modify is when the content last changed, and Change is when the metadata (permissions, owner) last changed. Your numbers will differ.

Comparing files#

Terminal
printf 'apple\nblueberry\ncherry\n' > fruits2.txt
diff fruits.txt fruits2.txt
diff -u fruits.txt fruits2.txt     # unified format, as used by git and patches
Output
2c2
< banana
---
> blueberry
--- fruits.txt	2026-10-01 10:51:52.599724793 +0530
+++ fruits2.txt	2026-10-01 10:51:52.627724585 +0530
@@ -1,3 +1,3 @@
 apple
-banana
+blueberry
 cherry

2c2 means "line 2 changed". In unified format, - lines are removed and + lines added. cmp compares binary files byte by byte, and sha256sum file prints a checksum for verifying downloads.

Viewing compressed files#

Logs are often rotated into .gz files. You don't need to decompress them first:

Terminal
gzip -k app.log                    # make app.log.gz, keep the original
zcat app.log.gz | tail -n 1        # print the decompressed contents
zgrep ERROR app.log.gz             # grep inside it
Output
2026-10-01 10:00:21 ERROR database timeout
2026-10-01 10:00:21 ERROR database timeout

zless pages through compressed files like less.

Which tool when?#

TaskCommand
Small file, print it allcat file
Big file, browse and searchless file
First / last lineshead -n N, tail -n N
Watch a growing logtail -F file
Count lineswc -l file
Unknown file typefile name
Differences between versionsdiff -u a b

Common mistakes#

  • cat-ing huge or binary files and flooding the terminal. Use less, or check with file first. If the terminal gets garbled, type reset.
  • Forgetting that tail -f keeps running. Press Ctrl+C to stop following.
  • Using tail -f on rotated logs. Use tail -F, which reopens the file when it's replaced.
  • Opening a file in an editor just to read it. That risks accidental changes; less is safer.

What's next#

Reading files is half the job; now you'll edit them with nano and vim.

Check your understanding

Quick quiz

0/3 answered
  1. 1.Which command is best for reading a 2 GB log file?

  2. 2.How do you watch new lines being written to a log file in real time?

  3. 3.What does wc -l access.log print?

Finished reading?

Mark this lesson complete to track your progress.