Module 3 · Text, redirection and pipes
Counting with wc
Lines, words and bytes: how wc counts, how to read its columns, and how to get a bare number for scripts.
What you will learn
- Read the three default columns of wc and select one with -l, -w or -c.
- Count several files at once and interpret the total line.
- Get a bare count from stdin and know what wc counts as a line and a word.
wc stands for *word count*, but it counts three things at once: newline characters, words and bytes. Given a file it prints the three numbers followed by the file name; given several files it prints one row per file plus a total row. It is the tool you reach for to answer "how many?" about almost anything, as long as that anything can be turned into lines first.
The options
| Option | Counts | Detail |
|---|---|---|
-l | lines | really newline characters; a last line without \n is not counted |
-w | words | runs of non-blank characters separated by spaces, tabs or newlines |
-c | bytes | file size; an accented letter in UTF-8 is 2 bytes |
-L | longest line | length in characters of the longest line |
Options combine: wc -lw prints lines and words only. Without options you get -lwc, always in that order (lines, words, bytes) regardless of how you typed the flags. BusyBox's wc has no -m for characters; -c counts bytes, which is the same thing for plain ASCII text.
~% cd /root/lab/l25
l25% cat poem.txt
the quick brown fox
jumps over
the lazy dog
l25% wc poem.txt
3 9 44 poem.txt
l25% wc -l poem.txt
3 poem.txt
l25% wc -l < poem.txt
3
l25% wc -l a.txt b.txt
3 a.txt
5 b.txt
8 total
l25% ls /etc | wc -l
19
l25% wc -L poem.txt
19 poem.txt
A bare number
When you want to use the count in a script, or compare it, the file name in wc's output gets in the way. Feed the file through stdin instead, either with < or a pipe, and wc prints only the number. wc -l < file is the idiom; cat file | wc -l is the same with one extra process. Combined with command substitution, n=$(wc -l < file) puts the count in a variable, something you will use constantly in the scripting module.
Counting things that are not files
Because wc reads stdin, anything that can be listed can be counted: ls /bin | wc -l for commands in a directory, grep -c aside grep error log | wc -l for matching lines, ps | wc -l for processes (minus one for the header), cat /etc/passwd | wc -l for user accounts. The pattern is always the same: produce one line per item, then wc -l.
Commands in this lesson
| Command | What it does |
|---|---|
wc file | Lines, words and bytes of file. |
wc -l file | Only the line count (plus the name). |
wc -w file | Only the word count. |
wc -c file | Only the byte count. |
wc -L file | Length of the longest line. |
wc -l < file | Bare line count, no file name. |
cmd | wc -l | Count the lines another command prints. |
Quiz
In what order does plain `wc file` print its numbers?
- words, lines, bytes
- lines, words, bytes
- bytes, words, lines
How do you get just the number of lines of notes.txt, with no file name?
- `wc -l notes.txt`
- `wc -l < notes.txt`
- `wc -n notes.txt`
A file was written with `printf 'a\nb\nc'`. What does `wc -l` report?
- 3
- 2
- 0
What does `wc -w` consider a word?
- A run of letters only
- Any run of non-blank characters separated by whitespace
- Anything found in the dictionary
Practice
/root/lab/l25/poem.txt is a short text. Store its number of words, and only the number, in /root/lab/l25/words.txt.
In /root/lab/l25 there are a.txt and b.txt. With a single wc command, write the line count of both files (including the total row) into /root/lab/l25/counts.txt.
Print only the number of bytes in /etc/passwd, without the file name.
Open this lesson in the app to do the tasks in a real Linux machine and have them checked.