wc

Count lines, words, bytes, or characters in text

Updated 2026-08-14

wc (word count) counts lines, words, bytes, or characters in its input. With no flags it prints all three of lines, words, and bytes; -l, -w, -c, or -m narrow it to just one.

The line count is really a newline count: wc -l counts \n characters, not visual lines. A file whose last line has no trailing newline is undercounted by one, which surprises people debugging an off-by-one somewhere else entirely.

-c counts bytes and -m counts characters; identical for plain ASCII, but they diverge on multi-byte UTF-8 text, where one character can span more than one byte. Multiple file arguments add a total line automatically; --total=always or --total=never overrides that. wc has no flag for "non-blank lines only", so grep -c . is the usual way to get that instead.

Sample files used on this page

Every example below was run against these files. Recreate them to follow along.

report.txt 40 numbered lines, each 5 words - hence 40 lines / 200 words

line 1 of the report
line 2 of the report
line 3 of the report

line 40 of the report

users.csv a header row plus 6 records

name,age,department
Alice,34,Engineering
Bob,29,Sales
Carol,41,Engineering
Dave,25,Marketing
Erin,38,Sales
Frank,31,Engineering

wordlist.txt 9 lines with deliberate duplicates and mixed case

banana
apple
Cherry
apple
date
banana
apple
Elderberry
cherry

access.log 10 requests in the standard combined log format

203.0.113.5 - - [13/Aug/2026:09:12:01] "GET /index.html HTTP/1.1" 200 512
203.0.113.5 - - [13/Aug/2026:09:12:03] "GET /style.css HTTP/1.1" 200 231
198.51.100.7 - - [13/Aug/2026:09:14:22] "GET /index.html HTTP/1.1" 200 512
198.51.100.7 - - [13/Aug/2026:09:14:25] "GET /missing.html HTTP/1.1" 404 162
203.0.113.5 - - [13/Aug/2026:09:15:47] "GET /index.html HTTP/1.1" 200 512
192.0.2.44 - - [13/Aug/2026:09:16:03] "POST /login HTTP/1.1" 302 0
192.0.2.44 - - [13/Aug/2026:09:16:04] "GET /dashboard HTTP/1.1" 200 4021
198.51.100.7 - - [13/Aug/2026:09:18:51] "GET /index.html HTTP/1.1" 200 512
203.0.113.5 - - [13/Aug/2026:09:19:10] "GET /api/status HTTP/1.1" 500 89
192.0.2.44 - - [13/Aug/2026:09:20:33] "GET /dashboard HTTP/1.1" 200 4021

crlf.txt two lines with Windows CRLF endings - 14 bytes, not 12

line1␍
line2␍

filelist.bin two filenames separated by NUL bytes, for --files0-from

report.txt␀wordlist.txt␀
25 outputs, collapsed by default

Counting lines, words, bytes, and characters

The four counting modes, each narrowed with a single flag.

Count lines

wc -l report.txt

-l counts newline characters - see the gotcha section below for what that means for a file with no trailing newline.

Show output
40 report.txt

Count words

wc -w report.txt

A 'word' is a maximal run of non-whitespace characters - the same definition most editors use for their own word count.

Show output
200 report.txt

Count bytes

wc -c report.txt

Raw byte count, regardless of content or encoding.

Show output
871 report.txt

Count characters

wc -m report.txt

Character count rather than byte count - identical to -c here because this file is plain ASCII, where every character is exactly one byte. They diverge on multi-byte UTF-8 text.

Show output
871 report.txt

Find the longest line

wc -L report.txt

-L reports the length of the longest line in the file, not a count at all - useful for deciding whether a file needs wrapping to fit a fixed-width display.

Show output
21 report.txt

Multiple files and totals

Count several files at once

wc -l users.csv wordlist.txt access.log

Each file gets its own line, plus an automatic total line summing them all.

Show output
  7 users.csv
  9 wordlist.txt
 10 access.log
 26 total

Force a total line even for a single file

wc -l --total=always report.txt

By default a lone file gets no total line since it would just repeat the count - --total=always prints one anyway, useful for consistent output in a script that sometimes gets one file and sometimes several.

Show output
40 report.txt
40 total

Combine short flags

wc -lw report.txt

Bundling -l and -w prints just those two counts, in that order, instead of all three defaults.

Show output
 40 200 report.txt

Reading from stdin

Count lines from a pipe

cat report.txt | wc -l

No filename to print, so just the bare number comes back.

Show output
40

Count lines from redirected input

wc -l < report.txt

Redirection and piping behave identically here - both feed wc's stdin, and both print just the number with no filename.

Show output
40

Count words in a single line

echo 'the quick brown fox' | wc -w

Works the same on a single echoed line as on a whole file.

Show output
4

Measure a string's length in characters

echo -n 'hello' | wc -c

-n on echo suppresses its own trailing newline, so this counts exactly the string's own length rather than length-plus-one.

Show output
5

The no-trailing-newline gotcha

A missing final newline undercounts by one

printf 'a\nb\nc' | wc -l

wc -l counts newline characters, not lines of text. This input has three lines of content but only two \n characters - the third line has nothing after it - so wc reports 2, not 3.

Show output
2

The same content, with a trailing newline, counts correctly

printf 'a\nb\nc\n' | wc -l

Identical visible content, one more trailing newline character, and the count matches what you would expect. Most editors add this automatically; some hand-built files and command substitutions don't.

Show output
3

Using wc on real things

Count total requests in a real access log

wc -w access.log

Not a meaningful metric on its own for a log file - shown here mainly to demonstrate that wc doesn't care what the text represents, it just counts.

Show output
90 access.log

Read a list of filenames from a NUL-separated file

wc -l --files0-from=filelist.bin

--files0-from reads the list of files to process from a NUL-separated file instead of the command line - the standard pairing with find -print0 when there could be too many files (or files with newlines in their names) for a normal argument list.

Show output
 40 report.txt
  9 wordlist.txt
 49 total

See the effect of hidden CRLF bytes

wc -c crlf.txt

The file holds two 'lineN' lines with a trailing \r\n each, and comes to 14 bytes - 2 more than plain Unix line endings would take, from the two extra \r bytes wc -l doesn't count as separate lines but wc -c still counts as bytes.

Show output
14 crlf.txt

The actual way to count only non-blank lines

printf 'a\n\nb\n\nc\n' | grep -c .

grep -c . counts lines matching 'at least one character' - every blank line fails that match and gets excluded. See the grep page for -c and other counting patterns.

Show output
3

Total lines across every file found, via find and xargs

find . -maxdepth 1 -name '*.csv' | sort | xargs wc -l

find locates the files, xargs hands them all to a single wc invocation so the total line covers every match - see the find page for more on pairing it with other commands.

Show output
  7 ./users.csv
  7 ./users2.csv
 14 total

Bundle lines and bytes together

wc -lc report.txt

Any combination of the short flags can be bundled - this prints just lines and bytes, skipping words and the default full trio.

Show output
 40 871 report.txt

Count how many accounts exist on a system

wc -l < /etc/passwd

/etc/passwd holds a line per account, so a headcount needs no parsing of the file's colon-separated fields at all.

Show output

Your output will differ: the number of accounts is whatever your machine has; a desktop install has far more than a container

21