Linux & Bash · Part I · Module 4 · Reading and Inspecting File Contents
Counting Lines, Words and Bytes
Every command so far in this module has shown you content. This one answers a different kind of question: not what is in the file, but how much of it there is. That sounds like the least interesting thing in the module and it is quietly one of the most useful, because a number is something you can compare, record, put in a report and act on, while a screenful of text is something you have to read. It is also the first command in this course with a genuine off-by-one in it — one that is entirely logical once you know the rule and that will otherwise silently give you the wrong answer.
Foundation14 min readLinuxPart IFundamentalsFilesMeasurement
Part I · Module 4 · Chapter 4.5 · Counting Lines, Words and Bytes
1. Turning a File Into a Number
$ wc five.txt
5 5 31 five.txtThree numbers and a name. The name wc is short for word count, which undersells it — it reports three counts at once, always in the same order:
5 5 31 five.txt
│ │ │ └── the file it is describing
│ │ └────── bytes
│ └────────────── words
└────────────────────── linesLines, words, bytes. That order never changes, and there are no headings, so knowing it is the whole skill of reading the output.
2. Asking for One Count
Most of the time you want one number, not three:
$ wc -l five.txt
5 five.txt
$ wc -w five.txt
5 five.txt
$ wc -c five.txt
31 five.txt| Option | Counts |
|---|---|
-l | lines |
-w | words |
-c | bytes |
-m | characters |
-l is used far more than the rest put together, because "how many lines" is a question that comes up constantly: how many results, how many errors, how many files in a list.
-c and -m are not the same
$ wc -c notes.txt
31 notes.txt
$ wc -m notes.txt
31 notes.txtIdentical here, and they will differ the moment the file contains anything outside plain English. A byte is a unit of storage; a character is a unit of text, and some characters — accented letters, symbols, anything non-Latin — take more than one byte.
For ordinary English text the numbers match. For anything else, -c tells you about storage and -m tells you about content. Chapter 2.5's size field is a byte count, so -c is what agrees with it.
What counts as a word
A word is a run of non-whitespace characters, separated by whitespace. That is the whole definition, and it means punctuation attaches to whichever word it touches:
$ printf 'hello, world\n' | wc -w
2Two words. The comma is part of hello, rather than a separator. Word counts are a rough measure and should be treated as one.
3. Several Files at Once
$ wc -l a.txt b.txt five.txt
2 a.txt
3 b.txt
5 five.txt
10 totalOne line per file, then a total. That total line is genuinely useful — it answers "how many lines across all of these" in one command — and it is also a trap worth knowing about, because the last line of output is not a file.
Combined with Chapter 3.5's patterns, this becomes a real tool:
$ wc -l *.log
412 run_1.log
398 run_2.log
455 run_10.log
1265 totalThree logs and their sizes at a glance. Chapter 3.5's rule applies exactly: the shell expanded *.log into three names before wc started, so wc received three operands and behaved as in the previous example.
4. The Newline Rule
Here is the off-by-one, and it is worth meeting deliberately rather than discovering in a report.
$ printf 'no trailing newline' > nonl.txt
$ cat nonl.txt
no trailing newline
$ wc -l nonl.txt
0 nonl.txtThe file plainly contains one line of text. wc -l says zero.
The explanation is exact: wc -l counts newline characters. It does not count lines; it counts the character that ends a line. That file has text but no final newline, so there are zero newline characters in it, so the answer is zero.
Notice also that cat ran the content straight into the next prompt — no line break — which is the visible symptom of the same thing and the quickest way to spot it.
By contrast, the byte count is unaffected:
$ wc -c nonl.txt
19 nonl.txtNineteen bytes of text, zero newlines.
5. Counting Something Other Than a File
wc can count what another command produced rather than what is in a file:
$ ls | wc -l
14Fourteen entries in this directory. ls produced a list, and wc -l counted the lines of it instead of reading a file.
Notice there is no file name in the output. When wc is given no file, it has nothing to name — the bare number is the tell that it counted something handed to it.
$ tail -n 100 run.log | wc -l
100That vertical bar is the pipe from Chapter 4.3, and Module 12 owns it. The reason to show it again here is that this is wc's most common real use: it is very often the last stage of a pipeline, turning whatever the earlier stages selected into a single number.
Everything later in this course that produces a count — how many tests failed, how many files matched — is this shape. Module 14's searching commands plus wc -l is the whole recipe, and Module 13 builds summaries out of it.
6. What a Number Is Good For
Three things you can do with a count that you cannot do with a screenful of text.
Compare. Two runs that should have produced the same output:
$ wc -l expected.txt actual.txt
482 expected.txt
485 actual.txt
967 totalThree lines different. That is not the whole story — Chapter 4.6 tells you which lines — but it takes one second and tells you whether to investigate at all.
Check that something happened.
$ wc -l results.txt
0 results.txtA file that exists and is empty, which Chapter 2.5 established is a different fact from a file that is missing. Something created it and wrote nothing.
Record. A number can go in a summary, be compared against yesterday's, or be the thing a later command decides on. A log cannot.
7. Why This Matters in Engineering Work
Counting is the foundation of every summary an engineer produces, and the reason is that nobody reads a thousand logs — they read a table of numbers derived from them.
$ wc -l sim/run_*/sim.log
412 sim/run_1/sim.log
398 sim/run_2/sim.log
0 sim/run_3/sim.log
455 sim/run_4/sim.log
1265 totalOne command, and run_3 stands out immediately: its log is empty, so that run produced nothing at all. That is a different failure from a run that produced a log full of errors, and the count found it without reading a single line.
This is also the simplest honest measurement available when you want to know whether a job is making progress — Chapter 4.4's buffering problem, answered with a number rather than by staring at a quiet screen.
Part II builds regression summaries, pass and fail tallies, and trend comparisons. All of them are counting, and all of them are this command at the end of a pipeline.
8. Practice
Question 1. wc notes.txt prints 12 47 310 notes.txt. What does each number mean?
Question 2. Which option gives lines, which gives words, and which gives bytes?
Question 3. A file contains visible text but wc -l reports 0. Explain exactly why, and give the symptom you would have seen from cat.
Question 4. When do -c and -m give different answers, and which one agrees with the size shown by ls -l?
Question 5. wc -l *.log prints four lines of output for three files. What is the fourth, and why is it worth being careful about?
Question 6. ls | wc -l prints a bare number with no file name. Why is there no name?
Question 7. printf 'hello, world\n' | wc -w prints 2, not 3. Explain, using the definition of a word.
Question 8. You have twenty run logs and want to spot any run that produced nothing. Write the single command, and say what you would look for in its output.
9. Remember
wcreports lines, words and bytes, always in that order, with no headings.-llines,-wwords,-cbytes,-mcharacters.-lis the one you will use constantly.-cis storage and-mis content. They agree on plain English text and diverge on anything else;-cis what matchesls -l.wc -lcounts newline characters, not lines. A file whose last line has no newline reports one fewer than you see. The tell iscatoutput running into your prompt.- A word is a run of non-whitespace, so punctuation sticks to its neighbour. Treat word counts as approximate.
- Several files produce a
totalline, which is useful and is not a file. - With no file,
wccounts what it was handed and prints a bare number — the shape of its most common real use, as the last stage of a pipeline. - A count is comparable, recordable and actionable in a way that a screenful of text is not. That is what makes this small command the basis of every summary.
Counting told you how many lines differ between two files. The next chapter tells you which ones, and in the format that every patch and code review on this planet uses.
Where this fits
Part of the Linux & Bash curriculum.
