Updated: 8 October 2026 · Applies to: Debian 13, Ubuntu 24.04 and 26.04 (GNU coreutils 9.7 and uutils 0.10.0, less 590 and 668, util-linux more 2.39 and 2.41)
To display a file in Linux, use cat for short files, less to page through long ones, head and tail to see the first or last lines, and tail -f to watch a log file while it grows:
cat notes.txt # print the whole file less app.log # scroll and search (q to quit) head -n 20 app.log # first 20 lines tail -n 50 app.log # last 50 lines tail -f app.log # follow new lines (Ctrl+C to stop)
The examples below use a 10-line application log, app.log.
cat: print whole files
cat prints one or more files one after the other. -n numbers the lines:
$ cat a.txt b.txt
Line A
Line B
Line C
$ cat -n a.txt b.txt
1 Line A
2 Line B
3 Line C
To join files into a new one, redirect the output: cat a.txt b.txt > all.txt (see redirecting command output).
cat -A makes invisible characters visible: ^M at a line end means Windows (CRLF) line endings, ^I is a tab, and $ marks the end of each line. This is the quickest way to find out why a config file edited on Windows misbehaves:
$ cat -A windows.conf server_name example.com;^M$ root /var/www/html;^M$
tac prints a file with the last line first and nl numbers it; see cat and tac with examples.
less: page through and search large files
less app.log opens the file one screen at a time and does not load it all into the terminal, so it works on logs of any size. The most useful keys (from less --help):
- Space or f: next screen. b: previous screen. Enter or j: one line down.
- g: first line. G: last line.
- /text then Enter: search forward. ?text: search backward. n and N: next and previous match.
- &text: show only the lines that match, like a live
grep. Type & and Enter with no text to show all lines again. - F: follow the end of the file like
tail -f. Press Ctrl+C to stop following and scroll again. - q: quit. h: help.
Handy options: less -N shows line numbers, less -S cuts long lines instead of wrapping them (good for wide logs), and less -i makes searches ignore case unless you type a capital letter. An option that starts with + is run as a command on start, so less +G app.log opens at the end and less +F app.log starts in follow mode.
If less asks may be a binary file. See it anyway?, answer n: the file is not text. Check what it is with file (see how to find out file types):
$ file app.log windows.conf app.log: ASCII text windows.conf: ASCII text, with CRLF line terminators
more: the older pager
more also shows a file one screen at a time (Space for the next screen, /text to search, q to quit), but it is simpler than less. Use it when less is not installed, which can happen in minimal containers. more +/ERROR app.log starts at the first line that contains ERROR.
head: the first lines
head prints the first 10 lines by default; -n sets another number:
$ head -n 3 app.log 2026-10-07 21:00:01 INFO worker started (pid 4121) 2026-10-07 21:00:02 INFO connected to database 2026-10-07 21:05:13 WARN slow query: 2.4 s
head -n -8 app.log: everything except the last 8 lines (here, the first 2).head -c 20 app.log: the first 20 bytes.- With several files,
headprints a==> app.log <==heading above each one.
tail: the last lines
$ tail -n 3 app.log 2026-10-07 21:20:00 INFO backup job queued 2026-10-07 21:31:47 ERROR disk /var at 91% 2026-10-07 21:32:00 INFO rotated logs
tail -n +9 app.log starts at line 9 and prints to the end. To print a range from the middle, use sed:
$ sed -n '4,6p' app.log 2026-10-07 21:10:44 INFO cache cleared 2026-10-07 21:15:09 ERROR payment API timeout after 30 s 2026-10-07 21:15:10 INFO retrying payment API
tail -f and tail -F: watch a log live
tail -f prints the last lines and then every new line as it is written, until you press Ctrl+C. Here a line was added from another session while tail was running:
$ tail -n 2 -f live.log 2026-10-07 21:31:47 ERROR disk /var at 91% 2026-10-07 21:32:00 INFO rotated logs 2026-10-07 21:40:05 INFO new request
Log files are rotated: the current file is renamed (for example to app.log.1) and a new one is created. tail -f keeps reading the old, renamed file, so new lines stop appearing. tail -F follows the file name instead and switches to the new file. When we rotated the log during a test on Debian 13, tail -f showed nothing more, while tail -F printed:
$ tail -n 1 -F rot.log 2026-10-07 21:32:00 INFO rotated logs tail: 'rot.log' has been replaced; following new file 2026-10-08 00:00:01 INFO after rotation 2026-10-08 00:00:02 INFO second line
To watch only errors, pipe it into grep; --line-buffered makes each match appear at once:
tail -F app.log | grep --line-buffered ERROR
Compressed logs and the systemd journal
Older rotated logs are often gzipped (app.log.2.gz). Read them without unpacking: zcat prints, zless pages and zgrep searches:
$ zgrep ERROR old.log.gz 2026-10-07 21:15:09 ERROR payment API timeout after 30 s 2026-10-07 21:31:47 ERROR disk /var at 91%
Many services log to the systemd journal instead of a text file. Read those with journalctl, for example journalctl -u nginx -f (see journalctl examples). For where each service writes its logs, see common log file locations.
Common mistakes
- Using
caton a huge log. It floods the terminal. Useless, ortail -n 100. - Printing a binary file.
caton a binary can leave the terminal showing strange characters. Typeresetand press Enter to fix it. - A missing last line break. If the last line of a file has no newline character, the shell prompt appears on the same line, right after the text. The file is fine;
cat -Ashows no$at the end of that line. - Using
tail -fon logs that rotate. Usetail -F, as shown above. - Writing
cat file | grep text. It works, butgrep text filereads the file itself; see grep, sort, uniq, wc, cut and tr.
Ubuntu 26.04 note
On Ubuntu 26.04, cat, head, tail, tac and nl come from uutils coreutils 0.10.0 (the Rust version). Every example above gave the same output as GNU coreutils 9.7 on Debian 13, except the messages of tail -F during a rotation: uutils printed tail: 'rot.log' has become inaccessible: No such file or directory and then tail: 'rot.log' has appeared; following new file. less and more are separate packages and are the same on both.
Related: list files with ls and match file names with wildcards.
Ucartz services for this topic
- KVM VPS hosting: NVMe SSD and full root access, with Free Basic Managed Support.
- Unmanaged dedicated servers: full root access and free IPMI KVM, with Free Basic Managed Support.
- Linux server management: hardening, patching, monitoring and automation for Ubuntu, Debian, RHEL and AlmaLinux.
