wc -w < file.txt prints how many words a file holds. Reading the file through < keeps its name out of the output; wc -w file.txt prints 9 greet.txt. macOS pads the number with spaces either way, so pipe it through tr -d ' ' if a script compares it.
printf '%s\n' 'Grüße aus Köln — see you at 9:00 👍🏽' > greet.txt
wc -w < greet.txt # words
# 9
wc -m < greet.txt # characters
# 36
wc -c < greet.txt # bytes
# 47
GNU coreutils 9.6 and macOS 27 print the same three numbers in a UTF-8 locale. The counter below says 7 words and 35 characters for the same text, final line break included.
What wc calls a word
POSIX defines a word for wc as a non-empty run of characters between white space, and nothing else counts. The dash — and the emoji are words to wc, and and/or would be one. The tool follows Unicode’s word rules (UAX #29): punctuation and emoji aren’t words, and 9:00 is one. On ordinary English prose the two agree closely. Text without spaces is where they part: 我吃苹果。今天天气很好。 is 1 word to wc and 6 to the tool.
-m against -c
-c counts bytes. In UTF-8, ü, ß and ö take two each, the dash three, and the emoji eight, because 👍🏽 is two code points, a thumbs-up and a skin-tone modifier, of four bytes each. -m counts characters as the locale defines them, which means code points: the emoji is 2 and the newline 1. The tool counts what you see, so the emoji is 1 and the total 35.
The locale decides
In the C or POSIX locale every byte is a character, so LC_ALL=C wc -m < greet.txt prints 47. The debian:13 Docker image sets no locale at all: wc -m there prints 47 until you run it with LANG=C.UTF-8.
Spaces other than the ASCII ones split words in some builds and not others. Counting a, one space character, then b:
GNU 9.7 GNU 9.7 macOS 27 macOS 27
C.UTF-8 POSIX en_US.UTF-8 C
U+00A0 no-break space 2 2 2 1
U+2003 em space 2 1 1 1
U+3000 ideographic 2 1 1 1
The tool splits words at all three.
Lines and the echo newline
wc -l counts newline characters, not lines: printf 'a\nb' | wc -l prints 1, where the tool’s Lines says 2. echo adds a newline, so echo "hello world" | wc -c prints 12 for 11 characters, and printf '%s' 'hello world' | wc -c prints 11. Word counts don’t change either way.
For a shell variable, wc -w <<< "$text" works in bash and zsh.