Linux wc Command: Count Lines, Words, Characters, and Bytes

wc is a command that counts the number of lines, words, bytes, and characters in a file or standard input. When run without options, it outputs the number of newlines, words, and bytes in order, and you can choose only the values you need with -l, -w, -c, and -m.

It is often used not only for simple statistics but also for checking the number of log entries, aggregating search results, verifying data files, and conditional judgments in shell scripts. However, you need to be aware that wc -l counts the number of newline characters, not the lines visible on the screen, and understand the difference between -c and -m when using them.

What is the wc command?

wc stands for word count, and it reads the entire input to count newlines, words, bytes, and characters. If no file is specified or a - is used in place of a filename, it reads from standard input, making it convenient to connect with other commands via a pipe.

In GNU wc, a word is a non-empty sequence of characters separated by whitespace. Since it does not determine grammatical words or words listed in a dictionary, strings with punctuation attached can also be counted as a single word.

Basic Grammar and How to Read Output

The basic syntax is as follows. Brackets indicate optional items and should not be included in the actual command.

wc [options] [file...]

If you specify a single file without any options, the number of lines, number of words, number of bytes, and the file name will be displayed.

wc notes.txt
12  48  317 notes.txt

The above result means that notes.txt contains 12 newline characters, 48 words, and 317 bytes. The spacing of the output fields may vary depending on the input, so you should not interpret the result based on the number of spaces.

To see only the value you need, specify the corresponding option.

wc -l notes.txt
wc -w notes.txt
wc -c notes.txt

Main options of wc

Option Calculation target Points to Note
-l, --lines Number of newline characters If the last line has no newline, that line is not included
-w, --words Number of words separated by spaces The determination of spaces may be affected by locale
-c, --bytes Number of bytes A multibyte character can have multiple bytes per character
-m, --chars Number of characters Affected by the current locale and character encoding
-L, --max-line-length Screen width of the longest line Not just a simple character count; tabs and wide characters are also considered
--files0-from=file A list of files separated by NUL characters GNU extension option, useful for handling filenames with special characters

You can also specify multiple options together. The output order is determined not by the order of the options but by the number of lines, words, characters, bytes, and maximum line length. For the exact definition and GNU extension options, you can refer to the official GNU Coreutils wc documentation.

How to accurately count the number of lines

wc -l counts newline characters

wc -l outputs the number of newline characters in the input, not the logical number of lines. For a typical text file, each line ends with a newline, so the result matches the number of lines, but if the last line does not have a newline, it may be one less than the visible lines.

wc -l access.log

You can check whether a text file ends with a newline by inspecting the last byte like this. If the result is 0a, it ends with an LF newline.

tail -c 1 notes.txt | od -An -t x1

Output only numbers without file name

If you pass a file as an argument, the file name will appear after the result. If you want to store only the numbers in a shell variable, use standard input redirection.

line_count=$(wc -l < notes.txt)
printf '%s\n' "$line_count"

GNU wc displays values without leading spaces when printing a single value, but if the script considers other implementations as well, it is safer to separately verify the number format.

Difference between byte count and character count

-c counts bytes

wc -c counts the number of bytes in the input. It is suitable for checking file size in bytes or calculating the actual size of data to be transferred.

wc -c document.txt

If you only need the size reported by the file system, stat may be more appropriate because it can obtain the value from metadata without reading the entire file.

stat -c '%s' document.txt

-m counts characters according to the locale

wc -m counts characters based on the current locale and encoding. In UTF-8, an ASCII character is 1 byte, whereas a non-ASCII character may use multiple bytes, so the results of -c and -m can differ for the same file.

printf 'Linux café\n' | wc -c
printf 'Linux café\n' | wc -m

In files with mixed incorrect encodings, the character count may differ from expectations. If the goal is character-based processing, check the current environment with locale and match it with the file encoding.

How is the word count calculated?

wc -w counts the number of non-empty strings separated by spaces. Consecutive spaces or tabs act as delimiters, and it does not remove punctuation or analyze the morphology of the language.

printf 'one  two\tthree\n' | wc -w
3

may not be suitable for natural language analysis or precise token counting in languages where words are not clearly separated by spaces. In such cases, a morphological analyzer or parser appropriate for the purpose should be used.

Checking the counts and totals for multiple files

Results by file and the total row

When multiple files are specified, a total row showing the overall sum is added after the results of each file.

wc -l january.log february.log march.log
  120 january.log
  135 february.log
   98 march.log
  353 total

Specifying the total display method with the GNU --total option

The latest GNU wc allows controlling the display of the total row with --total=auto, always, only, or never. If only the total number is needed, it can be used as follows.

wc -l --total=only january.log february.log march.log

--total is a GNU extension and may not be available in older Coreutils or other Unix-like environments. If portability is needed, check support using wc --help and use a method to handle the last line of the existing output.

Practical examples using pipes

Counting search result lines

You can count the number of matching lines by passing the grep results to wc -l.

grep 'ERROR' app.log | wc -l

If you only need the number of matching lines in a single file, grep -c 'ERROR' app.log is more direct. Both methods count a line only once even if the pattern appears multiple times in that line. For detailed search methods, refer to Linux grep command usage.

Checking the number of rows in CSV data

If the first row of a CSV file contains column names, you can skip the header using tail -n +2 and then count the data rows.

tail -n +2 data.csv | wc -l

For files where actual line breaks are allowed within CSV fields, a single record can occupy multiple physical lines, so you cannot accurately count the number of records in this way. Such files need to be processed with a CSV parser. You can check the method for specifying the range in tail at How to Use the Linux tail Command.

Counting file names safely even with special characters

The normal output of find can miscount the number of items if file names contain line break characters. In a GNU environment, you can separate file names with a NUL character and then count the number of NULs.

find ./logs -type f -name '*.log' -print0 | tr -cd '\0' | wc -c

This is safer for file names containing spaces and line breaks than simply using find... | wc -l. The search pattern *.log should be quoted so that the shell does not expand it first.

Checking the number of running processes

If GNU/Linux ps supports --no-headers, you can count the rows of the process list excluding the header.

ps -e --no-headers | wc -l

It is a snapshot at the moment the command is executed, and the results may vary depending on whether the pipeline's own processes are included or the implementation of ps. When using it as a monitoring metric, consider using dedicated tools or a /proc-based collection method.

Checking the length of the longest line

wc -L calculates the maximum width displayed on the screen, not the simple byte count or character count of the longest line. GNU wc takes wide characters into account based on the current locale and calculates tab stops in units of 8.

wc -L table.txt

Therefore, you should not assume that the -L result is the same as the character length obtained with awk '{ print length }' or the byte count from wc -c. For tasks that require an exact character count, such as code style checks, you should first verify the length definition used by the tool.

Safely handling many files

Avoiding command line length limits

When there are very many files, the shell's expansion of wildcards may exceed the command line length limit. GNU wc's --files0-from=- option reads a NUL-separated list of files from standard input to avoid this problem.

find ./logs -type f -name '*.log' -print0 | wc -l --files0-from=-

This command prints the number of lines in each log file and the overall total. It is safely passed even if the file names contain spaces or newlines because it uses NUL delimiters.

Be careful with totals divided by xargs

find... | xargs wc -l can be split into multiple wc executions when there are many files. In this case, each execution generates a separate total, making it difficult to read the overall total directly. In a GNU environment, --files0-from=- is better suited for aggregating the entire list at once.

Principles for use in shell scripts

Request only the value you need

Do not split the multiple columns of wc output without options by spaces; instead, request only the needed value with -l, -w, or -c. If the file name is not needed either, use input redirection.

bytes=$(wc -c < archive.dat)

Distinguish between errors and 0

The result 0 for an empty file and an error from failing to read the file have different meanings. If you store only the value, you may miss standard error or exit status, so in important automation, also check whether the command succeeded.

if count=$(wc -l < input.txt); then
 printf 'lines=%s\n' "$count"
else
 printf 'Could not read input.txt.\n' >&2
fi

Common Misunderstandings and Precautions

The result of wc -l is one less than expected

It is likely that the last line does not end with a newline character. wc -l counts the newline characters, so it does not include the incomplete final line. Before arbitrarily changing the original format, check the output rules of the program that generated the file.

-c and -m differ for multibyte characters

-c counts bytes, while -m counts characters. This difference is normal in multi-byte encodings like UTF-8. If the purpose is storage size, use -c; if the purpose is the number of characters recognized by humans, check the encoding and locale, and then use -m.

Can I count the number of files with ls output?

For normal filenames, ls | wc -l may seem simple, but it is not suitable for automation due to aliases, output formats, and filenames containing newlines. Use find to specify file types and search depth, and if handling arbitrary filenames, choose the NUL-separated method.

Frequently Asked Questions

What happens if you run wc without options?

By default, the number of lines, words, and bytes is output in that order. If you specify a file as an argument, the file name will also be displayed at the end.

What is the wc result for an empty file?

An empty file with no content has 0 for lines, words, and bytes. A file with just one newline character will show 1 for the wc -l result, and the byte count may vary depending on the newline format used.

Does wc -w count words accurately in every language?

wc -w counts strings separated by whitespace; it does not perform language-aware word segmentation. Treat the result as a whitespace-delimited count rather than a linguistic word count.

Can I count the number of lines in a directory itself?

wc is not a command to count directory entries directly. You need to create the list of files you want using commands like find and then aggregate the results. If there may be special characters in file names, use NUL characters as separators instead of newlines.

Summary

The number of lines can be checked with wc -l, the number of words with wc -w, the number of bytes with wc -c, and the number of characters with wc -m. The output without options shows lines, words, and bytes in order, and if multiple files are specified, the values for each file and the total sum are displayed.

For accurate results, remember that wc -l counts newline characters, bytes and characters can differ, and a NUL delimiter may be needed for the list of filenames. To look at other basic tools together, you can refer to a list of commonly used commands in Linux.

More in This Category
Linux find Command: Search Files by Name, Type, Size, and Time

Linux find Command: Search Files by Name, Type, Size, and Time

Learn how to search with Linux find by name, file type, size, and modification time, combine expressions, run commands safely, and verify targets before deletion.

Linux kill Command: Send a Signal to a Process ID

Linux kill Command: Send a Signal to a Process ID

Learn how to send a Signal to a Process ID with the Linux kill command, including practical examples, key options, and important precautions.

Linux gzip Command: Compress a File in gzip Format

Linux gzip Command: Compress a File in gzip Format

Learn how to compress a File in gzip Format with the Linux gzip command, including practical examples, key options, and important precautions.

Linux apt Command: Manage Packages on Debian and Ubuntu

Linux apt Command: Manage Packages on Debian and Ubuntu

Learn how to manage Packages on Debian and Ubuntu with the Linux apt command, including practical examples, key options, and important precautions.

Linux getent Command: Query Users, Groups, and Other NSS Databases

Linux getent Command: Query Users, Groups, and Other NSS Databases

Learn how to query Users, Groups, and Other NSS Databases with the Linux getent command, including practical examples, key options, and important precautions.

Linux whatis Command: Show One-Line Command Descriptions

Linux whatis Command: Show One-Line Command Descriptions

Learn how to use the Linux whatis command to display concise descriptions of commands and manual pages, with essential options, practical examples, output interpretation, and common troubleshooting tips.

Linux clear Command: Clear the Terminal Display

Linux clear Command: Clear the Terminal Display

Learn how to use the Linux clear command to clear the visible terminal screen and understand scrollback behavior, with essential options, practical examples, output interpretation, and common troubleshooting tips.

Linux rmdir Command: Remove Empty Directories

Linux rmdir Command: Remove Empty Directories

Learn how to remove empty directories with Linux rmdir, delete empty parent paths, diagnose failures, and understand when rm -r is different.

Linux Tutorial / Understand Users, Groups, and File Ownership

Linux Tutorial / Understand Users, Groups, and File Ownership

Understand UIDs, GIDs, primary and supplementary groups, and file ownership, then inspect them safely with id, groups, getent, ls, and stat.

Linux printenv Command: Print Environment Variable Values

Linux printenv Command: Print Environment Variable Values

Learn how to use the Linux printenv command to print all environment variables or selected variable values, with essential options, practical examples, output interpretation, and common troubleshooting tips.