sort and uniq: unique values and counting
Get a sorted list of unique words from a file.
How many distinct IPs visited the server, which address sends the most
requests, which error codes show up most often. You ask a log
questions like these every day. The answer is almost always the same
pipeline: sort | uniq -c | sort -rn. In this lesson we'll break down
what it's made of and where it's easy to get wrong.
Where to practice
Run the examples in an ubuntu:24.04 container. You can bring up the
same one yourself:
docker run --rm -it ubuntu:24.04 bash
On Linux, in WSL2, and on macOS, sort and uniq are already there,
and the lesson's commands work in your own terminal too. On Ubuntu
that's GNU coreutils; macOS has its own implementation. Everything in
this lesson behaves the same in both. The only difference is the width
of the padding before the counter in uniq -c, covered below.
Create a file with words to try things on:
printf 'apple\nbanana\napple\ncherry\nbanana\napple\ndate\n' > /tmp/words.txt
sort: order lines
sort reads lines from a file or from a pipe and prints them in order.
It doesn't change the file itself:
sort /tmp/words.txt
apple
apple
apple
banana
banana
cherry
date
By default, lines are compared as text, character by character. For
numbers this gives an unexpected order: 10 comes before 2, because
1 is less than 2. The -n flag turns on numeric comparison:
printf '10\n9\n100\n2\n' | sort -n
2
9
10
100
Without -n the same input comes out as 10, 100, 2, 9.
Three more flags come up all the time:
-rreverses the order: largest to smallest.-ukeeps one copy of each line after sorting.-ksorts by a field instead of the whole line.-k3,3nmeans "by the third field, as a number". The default field separator is a space; a different one is set with-t:sort -t, -k3,3nfor CSV.
Flags can be combined: sort -rn is the same as sort -r -n.
uniq: remove adjacent duplicates
uniq compares each line with the one before it and drops it if it's
the same. The key word here is "the one before it". Duplicates that
are spread across the file are invisible to uniq:
uniq /tmp/words.txt
apple
banana
apple
cherry
banana
apple
date
Nothing changed: in the original file, identical words aren't next to
each other. That's why sort almost always goes before uniq.
Sorting brings identical lines together, and then uniq collapses
them:
sort /tmp/words.txt | uniq
apple
banana
cherry
date
sort -u /tmp/words.txt gives the same result in one command.
Useful uniq flags:
-cputs the repeat count before the line.-dprints only the lines that had duplicates.-uprints only the lines with no duplicates.
sort /tmp/words.txt | uniq -c
3 apple
2 banana
1 cherry
1 date
The number is right-aligned with spaces. On Ubuntu the field is 7
characters wide, on macOS it's 4. If the result is read further by
awk or sort -n, the padding doesn't get in the way: both skip
leading spaces.
Finding the most frequent values
Now let's put the whole pipeline together. Take a list of IPs from a log:
printf '10.1.1.5\n10.1.1.9\n10.1.1.5\n10.1.1.7\n10.1.1.5\n10.1.1.9\n' > /tmp/ips.txt
sort /tmp/ips.txt | uniq -c | sort -rn | head -2
3 10.1.1.5
2 10.1.1.9
What each part does:
sortbrings identical addresses next to each other.uniq -ccollapses them and writes the count.sort -rnorders the lines by that number, largest to smallest.head -2keeps the first two lines.
In a real log, the IP isn't in its own file; it's the first field of
the line. Then you put awk '{print $1}' access.log at the front (the
awk lesson), or grep if you only need the lines with errors. The
order of the stages matters: first pick out the values, then sort,
then uniq -c, then sort again, and only at the end head.
Common mistakes
uniqwithoutsort. The result looks plausible, but one value shows up in it several times, and the counts are too low. If the output ofuniq -chas duplicates, there was no sort before it.headbeforesort -rn. The pipeline... | uniq -c | head -3 | sort -rntakes the first three lines alphabetically and only then sorts them by number. The most frequent value might not even make it into those three.- Numbers without
-n.sortwithout the flag puts100before9. Afteruniq -cthis is less noticeable because of the space padding, but on numbers with no padding (awk '{print $2, $1}', sizes, codes) the order breaks. - Invisible differences.
appleandapplewith a trailing space are different lines forsort -uanduniq, and both stay in the output.Appleandapplediffer the same way.sort -fignores case, and extra spaces need to be removed before sorting, for example withsed. - Redirecting into the same file.
sort words.txt > words.txtempties the file first (the shell opens it for writing beforesortruns), and the result is empty. Write to a different file, or usesort -o words.txt words.txt. - The order depends on the locale. The GNU
sortdocumentation warns that language settings (LANG,LC_ALL) change the sort order. If you need the same order on every machine, runLC_ALL=C sort: then bytes are compared, and uppercase letters come before lowercase ones.
What you'll need for the tasks
- Getting a list of unique values with
sort -uorsort | uniq. - Counting repeats with
sort | uniq -cand printing the most frequent ones withsort -rn | head. - Finding the bug in a finished pipeline: where
sortis missing, whereheadis in the wrong place. - In the mini-project: putting
find,grep,sedorawk, andsort | uniqfrom across the whole module into one pipeline.
Practice in your browser
Linux runs right here. Solve the task and we'll save your progress automatically.
Unique words in /tmp/uniq.txt
/tmp/words.txt has a list of words with repeats. Build a sorted list of unique words in /tmp/uniq.txt, one per line.
0%
Go through it with an AI agent
The agent explains anything unclear in plain words, gives you 3 labs for this lesson and drills you on interview questions. $49 one-time, lifetime access.
Tell the agent: use MCP izi, give me lesson terminal-text-05-sort-uniq
Progress saved in this browser
Clear your history or open this on your phone, and the marks will be gone. Leave your email and they'll move to your account. No password needed.
Done. moved to your account. You can see your progress on any device. My progress