Viewing Text Files
Before editing or processing a file, inspect it. A small configuration file, a large log, and a live stream of new log lines need different tools. Choosing the right viewer keeps the terminal usable, avoids loading unnecessary data, and reduces the chance of dumping binary control characters into your session.
The examples assume Ubuntu Server LTS with GNU Coreutils and less. You should already be comfortable with paths and safe lab work from File and Directory Commands.
Create a Sample Log
mkdir -p ~/lab/viewing-text
for n in $(seq 1 30); do
printf '%s level=INFO request_id=req-%03d message="test request"\n' \
"$(date -u +%FT%TZ)" "$n"
done > ~/lab/viewing-text/app.log
Verify it:
file ~/lab/viewing-text/app.log
stat -c 'size=%s bytes, mode=%A, file=%n' ~/lab/viewing-text/app.log
wc -l ~/lab/viewing-text/app.log
Expected result:
/home/<username>/lab/viewing-text/app.log: ASCII text
size=... bytes, mode=-rw-r--r--, file=/home/<username>/lab/viewing-text/app.log
30 /home/<username>/lab/viewing-text/app.log
The size and timestamp vary. The important part is that the file is text and has 30 newline-terminated records.
Check Before You Display
For an unknown file, inspect metadata before printing it:
Replace <file> with a real path. These checks answer three questions: how large is it, what type of content does it appear to contain, and can the current user read it?
Warning
Do not blindly cat binary files, disk images, compressed archives, or unknown device files. They may produce unreadable output, terminal control sequences, or a huge stream of data. Use file first, and for binary inspection use tools such as hexdump -C with a small byte limit.
cat: Print Small Files Completely
cat concatenates files to standard output. For one small file, it is a quick viewer:
For a 30-line lab file this is fine. For a 500 MB log, it is a poor choice because it floods your terminal and gives you no navigation.
Concatenate two files:
printf 'alpha\n' > ~/lab/viewing-text/a.txt
printf 'beta\n' > ~/lab/viewing-text/b.txt
cat ~/lab/viewing-text/a.txt ~/lab/viewing-text/b.txt
Output:
cat does not insert a separator between files. If the first file does not end with a newline, the next file's first line joins the same terminal line.
Useful display options:
-n numbers output lines. GNU -A makes tabs, line ends, and some non-printing characters visible. It is useful when whitespace or missing newlines matter.
less: Page Through Large Files
Use less when the file is larger than one screen or when you need search:
Common keys inside less:
Spaceorf: one screen forward.b: one screen backward.g: beginning of file.G: end of file./request_id=req-020: search forward.nandN: next and previous match.q: quit.
Line numbers and long-line handling:
-N displays line numbers. -S chops long lines visually instead of wrapping them; use horizontal movement keys to inspect the rest. The file itself is not modified.
more is another pager and may be present in rescue environments. less is usually more comfortable because it supports backward movement and richer search.
head: Inspect the Beginning
By default, head prints the first 10 lines:
Print exactly five lines:
Sample output:
2026-07-29T06:00:00Z level=INFO request_id=req-001 message="test request"
2026-07-29T06:00:00Z level=INFO request_id=req-002 message="test request"
2026-07-29T06:00:00Z level=INFO request_id=req-003 message="test request"
2026-07-29T06:00:00Z level=INFO request_id=req-004 message="test request"
2026-07-29T06:00:00Z level=INFO request_id=req-005 message="test request"
Your timestamp will differ. The important part is that the first five records are shown.
Byte-based sampling:
-c counts bytes, not characters. It can cut a UTF-8 character in the middle. For normal line-oriented logs, prefer -n.
tail: Inspect the End and Follow Growth
By default, tail prints the last 10 lines:
Start from a specific line with +N:
In a 30-line file, that prints lines 26 through 30. The + changes the meaning from "last N lines" to "starting at line N".
Following Logs
Run this in one terminal:
In another terminal, append a line:
printf '%s level=ERROR request_id=req-031 message="database timeout"\n' \
"$(date -u +%FT%TZ)" >> ~/lab/viewing-text/app.log
The first terminal shows the new line. Stop tail -f with Ctrl+C.
GNU tail -f follows the file descriptor by default. If a log is rotated by rename, the process may continue following the old file. For name-based following:
-F is equivalent to --follow=name --retry in GNU Coreutils. It is useful for many log rotation setups. If an application writes to systemd-journald instead of a plain file, use journalctl -f -u <service> rather than tail.
Counting with wc
Without options, wc prints lines, words, and bytes. wc -l counts newline characters, not visual rows.
Example without a final newline:
printf 'first\nsecond' > ~/lab/viewing-text/no-final-newline.txt
wc -l ~/lab/viewing-text/no-final-newline.txt
Output:
The file has two visible lines but only one newline character.
Standard Output and Standard Error
If cat cannot open a file, the error goes to standard error:
Typical output:
Redirecting standard output does not hide standard error:
The error still appears on the terminal. The output file may still be created or truncated because Bash opens redirections before starting cat. Avoid unnecessary > when your goal is only to view.
Pipes and redirection are covered later in the text and stream section.
When You Cannot Read the File
Many production logs are not world-readable, especially anything under /var/log written by a service running as its own system account:
This is not a bug in tail; it is the permission system working as intended. Diagnose it in order:
Compare the file's owner and group against your own user and group memberships. Three common fixes, in order of preference:
- If your account belongs to a group that already has read access (commonly
admon Debian/Ubuntu for most system logs), the fix is being added to that group, not escalating to root for every read:sudo usermod -aG adm <username>, then start a new login session for the group change to take effect. - If no group grants the access you need and one-off reads are acceptable,
sudo tail -n 20 /var/log/auth.logis appropriate for an administrator diagnosing a real incident. - If several specific users need standing read access without a broad group, a
setfaclentry on the log file is a more precise tool than either of the above, though the logging service itself may reset permissions on rotation; that is a topic for the permissions and ACL articles.
Do not respond to a Permission denied on a log file by changing its mode with chmod — that widens access for every user on the system, including ones who should never see authentication or application logs, and a log rotation tool will typically reset your change on the next rotation anyway.
Practical Scenario: Find the Latest Error Context
Problem: a service wrote a large app.log, and you need the most recent error without editing the file.
Check the file:
log="$HOME/lab/viewing-text/app.log"
file "$log"
stat -c 'size=%s modified=%y' "$log"
test -r "$log" || echo "not readable"
Append one error for the lab:
printf '%s level=ERROR request_id=req-032 message="cache unavailable"\n' \
"$(date -u +%FT%TZ)" >> "$log"
Inspect the end:
Search directly:
Sample output:
31:2026-07-29T06:00:00Z level=ERROR request_id=req-031 message="database timeout"
32:2026-07-29T06:01:00Z level=ERROR request_id=req-032 message="cache unavailable"
Conclusion: tail narrows the time window, less lets you inspect context, and grep -n gives line numbers for exact matches.
Common Mistakes
- Using
catfor huge files and losing useful terminal history. - Forgetting that
tail -fkeeps running until interrupted. - Assuming
tail -ffollows a log filename through every rotation method. - Using
head -con UTF-8 text and cutting a character in the middle. - Reading
wc -las "number of visible lines" instead of "number of newline characters". - Redirecting output while trying only to view a file, causing accidental truncation.
Exercises
- Create a 50-line file in
~/lab/viewing-textand show only its first seven lines. - Show only the last five lines, then show from line 46 to the end using
tail -n +46. - Open a file with
less -N -S, search for a request ID, and quit without modifying anything. - Create a file without a final newline and explain why
wc -lreports one fewer line than expected.
Verification criterion: you should be able to choose between cat, less, head, and tail based on file size, location of the needed data, and whether the file is still growing.
References
- GNU Coreutils manual: https://www.gnu.org/software/coreutils/manual/coreutils.html
catinvocation: https://www.gnu.org/software/coreutils/manual/html_node/cat-invocation.htmlheadinvocation: https://www.gnu.org/software/coreutils/manual/html_node/head-invocation.htmltailinvocation: https://www.gnu.org/software/coreutils/manual/html_node/tail-invocation.htmlwcinvocation: https://www.gnu.org/software/coreutils/manual/html_node/wc-invocation.htmllessmanual page: https://man7.org/linux/man-pages/man1/less.1.html