Linux & Bash · Part I · Module 4 · Reading and Inspecting File Contents
The Beginning and End of a File: head and tail
[Chapter 4.2](/linux-bash/paging-files-with-less) gave you a way to explore a long file interactively. Often you do not want to explore it at all — you want one specific thing, printed, so you can get back to work. Two commands cover most of those cases, because most of what you want from a large file lives at one end or the other. The top of a file tells you what kind of file it is, who wrote it and with what settings. The bottom tells you how whatever produced it finished. Both commands return instantly whatever the size, and used together they can pull out any range of lines from the middle as well.
Foundation15 min readLinuxPart IFundamentalsFilesLogs
Part I · Module 4 · Chapter 4.3 · The Beginning and End of a File
1. Sampling, Not Reading
The useful idea behind both commands: you rarely need a whole file, you need enough of it to answer a question.
run.log — 1,482 lines
┌──────────────────────────────────────────────────┐
│ line 1 Simulator v2024.3 ┐ │
│ line 2 Started 2026-03-22 09:04:11 │ head -n 3
│ line 3 Reading filelist rtl.f ┘ │ ← what IS this file?
│ ... │
│ ... │
│ line 1480 ERROR: assertion failed at 41200 ┐ │
│ line 1481 Simulation terminated │ tail -n 3
│ line 1482 Exit status 1 ┘ │ ← how did it END?
└──────────────────────────────────────────────────┘Those are genuinely different questions. The top of a file is identification — what produced it, when, with what inputs. The bottom is outcome — did it finish, did it fail, what was the last thing that happened.
Neither command reads the whole file to answer. Both are instant on a file of any size.
2. head — the First Lines
With no options, ten lines:
$ head run.log
Simulator v2024.3
Started 2026-03-22 09:04:11
Reading filelist rtl.f
Compiling 42 source files
...Ask for a specific number with -n:
$ head -n 3 five.txt
alpha
bravo
charlieChapter 1.5's grammar applies: -n is a short option that takes a value, and 3 is that value rather than an operand. Which is why head -n 3 five.txt has one file in it, not two.
Several files at once, and head labels them:
$ head -n 2 a.txt b.txt
==> a.txt <==
one
two
==> b.txt <==
one
TWOThe headers appear because there is more than one file — the same per-program convention Chapter 2.4 noted for ls.
Counting bytes instead of lines
$ head -c 10 five.txt
alpha
brav-c takes characters rather than lines, and it will cut mid-line, as it did there. Useful for peeking at a file whose "lines" might be enormous, or when you are not sure the file is line-based at all.
3. tail — the Last Lines
Symmetric, and in practice used more often:
$ tail run.logTen lines by default, and -n for a specific count:
$ tail -n 3 five.txt
charlie
delta
echoThe reason tail gets used more: for anything that was produced over time — a log, a build, a run — the interesting part is almost always at the end. The beginning is setup; the end is what happened.
$ tail -n 20 sim/run_042/sim.log
...
ERROR: assertion failed at time 41200
Simulation terminated
Exit status 1Twenty lines, instantly, from a file of any size. Compare that with Chapter 4.1's two-gigabyte cat: same file, same question, one is immediate and the other is a mistake.
4. tail -n +N — From a Line Onward
The form nobody discovers by accident, and it reads oddly until explained.
$ tail -n +3 five.txt
charlie
delta
echoA plus before the number changes the meaning completely:
| Form | Means |
|---|---|
tail -n 3 | the last three lines |
tail -n +3 | everything from line 3 to the end |
So the plus switches from counting back from the end to starting at a line and continuing.
The common use is skipping a header:
$ tail -n +2 results.csvThat prints a data file without its first line — exactly what you want when the first line is column names rather than data.
5. Both Together: Any Range You Like
Neither command can give you the middle of a file. Together they can, and this is the standard idiom:
$ head -n 4 five.txt | tail -n 2
charlie
deltaWork out what happened. head -n 4 produces the first four lines — alpha, bravo, charlie, delta. tail -n 2 then takes the last two of those four — charlie and delta, which are lines 3 and 4 of the original.
The arithmetic, stated so you can aim it:
head -n END | tail -n (END - START + 1) gives lines START..ENDFor lines 100 to 120 of a log:
$ head -n 120 run.log | tail -n 21120 is the last line wanted; 21 is how many lines from 100 to 120 inclusive.
6. Reading the Top of an Unfamiliar File
A practical routine, combining this chapter with Chapter 2.5.
$ ls -lh mystery.dat
-rw-r--r-- 1 engineer engineer 847M Mar 22 10:02 mystery.dat
$ head -n 5 mystery.dat
timestamp,signal,value
0,clk,0
5,clk,1
10,clk,0
15,clk,1Three facts in two commands: it is 847 MB, it is text, and it is comma-separated data with a header row. You now know how to read the rest of it and that you should not cat it.
Had the head produced garbled characters instead, the file is not text — and Chapter 4.1 explained what that can do to your terminal. The safer order is file first, which is Chapter 4.7.
7. The Failures
Asking for more lines than the file has. Not an error — you get the whole file:
$ head -n 1000 five.txt
alpha
bravo
charlie
delta
echoFive lines exist, five are printed. head and tail never complain about this, which makes them safe to use on a file whose length you do not know.
Forgetting the value belongs to -n.
$ head -n run.log
head: run.log: invalid number of lines-n consumed run.log as its value, leaving no file to read. This is Chapter 1.5's "an option that takes a value takes the next word" rule, producing a message that names your file as if it were a number.
Expecting tail to show changes. tail prints the last lines at the moment it runs and exits. If the file is still being written, what you saw is already out of date. The next chapter is exactly that problem.
A file with no final newline. The last line may look odd or run into your prompt. That is Chapter 4.5's and Chapter 4.7's territory, and it is a property of the file rather than a fault in tail.
8. Why This Matters in Engineering Work
tail is probably the most-typed command in day-to-day engineering work, for one reason: the answer to "what happened?" is at the end of the log.
$ tail -n 30 sim/run_042/sim.logThirty lines tell you whether a run passed, failed, or was killed — and they arrive instantly regardless of whether the log is 10 KB or 10 GB.
head earns its place differently. The top of a log records the conditions: which version of a tool, which input list, which settings, which machine. When two runs behave differently and should not have, comparing the first twenty lines of each is often the whole investigation — and Chapter 4.6's diff is the command that does that comparison for you.
The range idiom from §5 matters when an error message names a line number. "Problem at line 8,412" is directly actionable:
$ head -n 8420 build.log | tail -n 20That shows the failing line with context on either side, without opening the file.
9. Practice
Use a file five.txt whose lines are alpha, bravo, charlie, delta, echo.
Question 1. What does head -n 2 five.txt print? What does tail -n 2 five.txt print?
Question 2. What does tail -n +2 five.txt print, and how does the plus change the meaning?
Question 3. Write a single command line that prints only bravo and charlie. Show your arithmetic.
Question 4. head -n 100 five.txt — is this an error? What is printed?
Question 5. A build log is 400,000 lines and an error message says the problem is at line 215,300. Write the command that shows that line with ten lines on either side.
Question 6. head -n run.log reports invalid number of lines. Explain what the shell passed and what head did with it, using Chapter 1.5's rule.
Question 7. Two runs produced different results and should not have. Which end of each log would you compare first, and why that end rather than the other?
Question 8. For each, choose cat, less, head or tail: a 20-line config; how a 3 GB run finished; what format an unknown 800 MB data file is in; exploring a log around a known error.
10. Remember
- Sample, do not read. You almost never need a whole file — you need one end of it.
- The top identifies the file: what produced it, when, with what settings. The bottom gives the outcome.
head -n Nandtail -n Ntake their count as the value of-n, and are instant on a file of any size.-ccounts characters instead of lines, and will cut mid-line.tail -n +Nmeans from line N to the end — the plus flips it from counting back to counting forward. The usual use is skipping a header row.head -n END | tail -n (END-START+1)extracts any range. The|is a pipe, and Module 12 owns it.- Asking for more lines than exist is not an error, which makes both commands safe on files of unknown length.
tailshows the file as it is now and exits. For a file still being written, that is the next chapter.- Open an unfamiliar file with
ls -lhthenhead -n 5. Two commands, no risk.
Both commands in this chapter print what is there and return. The next one keeps the command running and shows you each new line as it is written — and covers the two situations where that quietly stops telling you the truth.
Where this fits
Part of the Linux & Bash curriculum.
