Viewing File Contents
On a Linux server you spend a huge amount of time just reading files: config files, log files, scripts, and plain text. You usually do not want to open a text editor for that, because you only want to look, not change anything. Ubuntu ships with a handful of small, fast commands built exactly for reading: cat, less, head, and tail. Learning when to reach for each one is one of the most practical Linux skills there is, especially tail -f, which lets you watch a log file update live while you debug a running service.
Why not just open an editor?
When you are administering a server (Ubuntu 22.04 or 24.04 LTS), opening every file in a text editor (a program for changing files, like nano or vim) is slow and risky. You might accidentally edit a production config. The viewing commands below are read-only: they print the file to your terminal and never touch the original. That makes them safe to run on anything, including system files you should not modify by hand.
These commands also work beautifully with pipes (the | symbol, which sends one command’s output into another command). For example, you can filter a huge log down to the lines you care about. We will show a few of those combinations as we go.
cat — print a whole file
cat (short for “concatenate”) dumps the entire contents of a file straight to your screen. It is perfect for short files.
cat /etc/hostname
Output:
web-prod-01
You can print several files at once, and cat -n numbers every line, which is handy when an error message references a line number.
cat -n /etc/timezone
Output:
1 Etc/UTC
When to use cat: short files you want to see all at once (a 5-line config, a small script). When NOT to: large files. Running cat /var/log/syslog will flood your terminal with thousands of lines that scroll past faster than you can read. For anything big, use less.
less — scroll through big files
less opens a file in a scrollable, searchable viewer without loading the whole thing into memory, so it stays fast even on multi-gigabyte logs. It is the right default for any file you are not sure about.
less /var/log/syslog
This opens an interactive screen. Inside less you control it with the keyboard:
| Key | What it does |
|---|---|
Space / f | Page down |
b | Page up |
| Arrow keys | Move one line at a time |
/word | Search forward for “word” |
n / N | Next / previous search match |
G | Jump to the end of the file |
g | Jump to the start of the file |
q | Quit and return to the shell |
Tip:
less +F /var/log/syslogstarts in “follow” mode (liketail -fbelow) but lets you pressCtrl-Cto stop following and scroll back through history, thenFto resume. It is the best of both worlds for log spelunking.
When to use less: any large file, or when you need to search inside it. The older more command does something similar but only scrolls forward — less is strictly better (hence the joke “less is more”).
head — the first lines
head prints only the start of a file. By default it shows the first 10 lines. Use -n to ask for a specific number.
head -n 5 /etc/passwd
Output:
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
When to use head: checking a file’s header (like a CSV column row), or peeking at the top of a file without printing the whole thing.
tail — the last lines
tail is the mirror image of head: it prints the end of a file, the last 10 lines by default. This is what you want for logs, because the newest events are always written at the bottom.
tail -n 20 /var/log/auth.log
Output:
2026-06-15T09:12:44.103Z web-prod-01 sshd[2041]: Accepted publickey for deploy from 203.0.113.9 port 50122 ssh2
2026-06-15T09:12:44.110Z web-prod-01 sshd[2041]: pam_unix(sshd:session): session opened for user deploy(uid=1000)
2026-06-15T09:13:02.555Z web-prod-01 sudo: deploy : TTY=pts/0 ; PWD=/home/deploy ; USER=root ; COMMAND=/usr/bin/systemctl restart nginx
tail -f — watch a log live
The single most useful flag in this whole page is -f (“follow”). tail -f prints the end of the file and then keeps the command running, printing new lines the instant they are written. When you restart a service and want to see what happens in real time, this is the tool.
sudo tail -f /var/log/nginx/error.log
Output:
2026/06/15 09:20:01 [error] 1502#1502: *88 connect() failed (111: Connection refused) while connecting to upstream, client: 198.51.100.4, server: example.com, request: "GET /api/health HTTP/1.1", upstream: "http://127.0.0.1:3000/"
Leave it open in one terminal, then trigger the bug (reload the page, hit the API) in another, and watch the error appear live. Press Ctrl-C to stop following.
You can follow several logs at once and even filter as they stream:
sudo tail -f /var/log/nginx/access.log | grep " 500 "
This shows only requests that returned a 500 (server error) status as they happen.
Gotcha: some Ubuntu services (anything using
systemd) write logs to the journal, not to a plain file, sotail -fon/var/logmay show nothing. For those, usejournalctl -u nginx -f, which is the systemd equivalent oftail -ffor a single service.
Quick comparison
| Command | Shows | Best for | Stays open? |
|---|---|---|---|
cat | Whole file | Short files, piping | No |
less | Scrollable view | Large files, searching | Yes (interactive) |
head | First N lines | File headers, top peek | No |
tail | Last N lines | Recent log entries | No |
tail -f | Last lines + live updates | Debugging running services | Yes (follows) |
Best Practices
- Default to
lesswhen you are unsure of a file’s size — it never floods your terminal. - Keep a
tail -fof the relevant log open in a spare terminal whenever you restart or deploy a service, so you catch errors the moment they appear. - Use
journalctl -u <service> -finstead oftail -ffor systemd-managed services like nginx, ssh, or postgresql. - Combine these tools with
grepvia pipes (tail -f app.log | grep ERROR) to cut noise down to only what matters. - Use
sudofor protected logs in/var/log(most auth and service logs need it), but never usesudowith an editor just to read — viewing is enough. - Prefer
head -nandtail -novercatfor big files so you only pull the slice you need.