Skip to content

Viewing File Contents

💡
Before you start

You need a Linux machine, or any terminal on macOS — nothing is installed and nothing is bought. Every command on this page is read-only or works inside a practice folder you create and can delete afterwards, and none of them needs sudo. If you have never opened a terminal at all, start with Introduction to the Linux Terminal, which shows you where it is and how to get your bearings.

Displaying Entire Files with cat

The cat (concatenate) command is the simplest way to display a file's contents. It reads the entire file and prints it to your terminal in one go.

# Display the contents of a file
cat /etc/hostname

# Display with line numbers
cat -n /etc/hosts

# Display multiple files sequentially
cat file1.txt file2.txt

Example output with line numbers:

$ cat -n /etc/hosts
     1  127.0.0.1       localhost
     2  127.0.1.1       mycomputer
     3
     4  # IPv6
     5  ::1             localhost ip6-localhost ip6-loopback
💡
When to use cat

cat is best for small files -- configuration files, short scripts, or quick checks. For anything longer than a screenful of text, use less instead, because cat will flood your terminal and scroll past too fast to read.

Useful cat Variations

cat -n Number all output lines. Helpful for referencing specific lines.
cat -b Number only non-blank lines. Cleaner output for files with many empty lines.
cat -s Squeeze consecutive blank lines into a single blank line.

Scrolling Through Files with less

The less command opens a file in a scrollable viewer. Unlike cat, it does not dump everything to the screen at once. Instead, it shows one screenful at a time and lets you navigate forward and backward.

# Open a file in less
less /var/log/syslog

# Open with line numbers
less -N /var/log/syslog

Once inside less, use these keys to navigate:

Space / Page Down Move forward one full screen.
b / Page Up Move backward one full screen.
j or Down Arrow Move forward one line.
k or Up Arrow Move backward one line.
g Jump to the beginning of the file.
G Jump to the end of the file.
/pattern Search forward for "pattern". Press n for next match, N for previous.
q Quit and return to the terminal.
💡
less is the go-to file viewer.

System administrators and developers use less constantly for reading log files, configuration files, and source code. The search feature (/pattern) is especially powerful -- you can search through thousands of lines in an instant.

Peeking at the Start with head

Sometimes you only need to see the beginning of a file. The head command prints the first lines of a file -- by default, the first 10 lines.

# Show the first 10 lines (default)
head /etc/passwd

# Show the first 5 lines
head -n 5 /etc/passwd

# Show the first 20 lines
head -n 20 /var/log/syslog

head is commonly used to quickly check what a file contains without loading the whole thing. For example, you might use it to verify a CSV file has the right column headers, or to check the top of a log file for startup messages.

# Check the header of a CSV file
head -n 1 data.csv

# Peek at a configuration file
head -n 15 /etc/nginx/nginx.conf

Watching the End with tail

The tail command is the opposite of head: it prints the last lines of a file. By default, it shows the last 10 lines.

# Show the last 10 lines (default)
tail /var/log/syslog

# Show the last 20 lines
tail -n 20 /var/log/syslog

# Show the last 50 lines
tail -n 50 /var/log/auth.log

Live Log Monitoring with tail -f

The most powerful feature of tail is the -f (follow) flag. It keeps the file open and prints new lines as they are added in real time. This is essential for monitoring log files while troubleshooting.

# Follow a log file in real time
tail -f /var/log/syslog

# Follow the last 50 lines and continue watching
tail -n 50 -f /var/log/auth.log

While tail -f is running, every new line written to the file appears on your screen instantly. Press Ctrl + C to stop following and return to the terminal prompt.

⚠️
Some log files require sudo.

System log files like /var/log/auth.log or /var/log/syslog may not be readable by regular users. If you get a "Permission denied" error, prepend the command with sudo: sudo tail -f /var/log/auth.log.

Counting with wc

The wc (word count) command tells you how many lines, words, and bytes are in a file. It is a quick way to gauge the size or length of text content.

# Full count: lines, words, bytes
wc /etc/passwd
  45   68  2467 /etc/passwd

# Count only lines
wc -l /etc/passwd
45 /etc/passwd

# Count only words
wc -w readme.txt

# Count only characters
wc -c data.csv
wc -l Count lines. Most commonly used. Answers "how many entries/records?"
wc -w Count words (sequences of non-whitespace characters).
wc -c Count bytes. Useful for checking file sizes.
wc -m Count characters (handles multi-byte encodings like UTF-8 correctly).

A common use case is counting lines in a log file to see how many events were recorded, or counting lines of code in a project:

# How many lines in the system log?
wc -l /var/log/syslog

# How many users on the system?
wc -l /etc/passwd

Now Do It Yourself: Five Steps

Most real terminal work is reading files you did not write — logs, configuration, output from something else. You will make a small log file and then answer questions about it without opening an editor. Nothing needs sudo, and every output below is exactly what the terminal printed.

1
Create a file with known contents

Go: open a terminal, run cd to go home, then mkdir -p practice and cd practice.

Do: run this to create a small log. The > sends the output into a file instead of the screen.

printf 'error: disk full\ninfo: started\nerror: timeout\ninfo: done\n' > app.log

You should see: no output. Confirm it worked with cat app.log, which should print all four lines in that order.

If not: if you see the \n characters literally rather than line breaks, you used echo instead of printf — plain echo does not interpret them on every system, while printf always does. ⚠️ Note > replaces the whole file every time; >> adds to the end. Using the wrong one on a real file destroys it silently.

2
Read the ends of a file instead of all of it

Go: same folder.

Do: run head -2 app.log, then tail -2 app.log.

You should see: the first two lines, then the last two. On a four-line file this is a curiosity; on a log with two million lines it is the difference between an instant answer and flooding your screen. tail is the one you will reach for most, because the newest entries are at the bottom.

If not: if head prints everything, the file has fewer lines than you asked for — that is not an error, it simply gives you what exists. For a live log, tail -f stays open and prints new lines as they arrive; press Ctrl + C to stop it.

3
Count instead of reading

Go: same folder.

Do: run wc -l app.log.

You should see: 4 app.log — the number of lines, then the filename. wc is "word count" and -l asks for lines specifically.

If not: if the number is one lower than you expect, the last line has no newline at the end — wc -l counts line endings, not lines. That is a real distinction that surprises people when scripting, and it is why the printf in step 1 finishes with \n.

4
Search inside the file

Go: same folder.

Do: run these three, one at a time.

grep error app.log
grep -c error app.log
grep -n error app.log

You should see: the two matching lines; then 2; then the same two lines prefixed 1: and 3:. -c counts instead of printing, and -n adds line numbers so you can go straight to the spot in an editor. These three cover most of what anyone ever needs from grep.

If not: nothing printed means nothing matched — and grep is case-sensitive, so grep ERROR app.log finds nothing here. Add -i to ignore case. When a search "should" match and does not, capitalisation is the first thing to suspect.

5
Join the tools together with a pipe

Go: same folder.

Do: run grep error app.log | wc -l, then run grep zebra app.log.

You should see: 2 from the first — | feeds one command's output straight into the next, so wc counted only the matching lines rather than the whole file. The second prints nothing at all, because nothing matched.

If not: that silence is worth understanding: grep also sets an invisible exit code, 1 when it finds nothing, which is how scripts test for a match. Check it with echo $? immediately afterwards — it prints 1 after the failed search and 0 after a successful one. Piping is the whole philosophy of the terminal: small tools, joined up.

🎉
Check yourself before moving on

Without scrolling up: you search a log you are certain contains the word and grep prints nothing. What do you try first? Answer: -i, to ignore case. grep matches exactly as typed, so Error and error are different words to it.

Now do it without the page: in one command, count how many lines of app.log are not errors. You need grep's invert option -v and a pipe — step 5's shape, with one flag added.

Summary

You now have a toolkit of commands for reading and inspecting files:

  • cat -- Display entire files (best for short files)
  • less -- Scroll through files interactively (best for large files)
  • head -- View the first N lines of a file
  • tail -- View the last N lines; use -f to follow live updates
  • wc -- Count lines, words, and characters in a file

Choosing the right tool depends on the situation: cat for quick peeks, less for reading, head / tail for targeted views, and wc for measuring.

🎉
Nice work!

You can now read and inspect files without opening a text editor. Next up, you will learn about Linux file permissions -- what rwx means and how to control who can read, write, and execute your files.