sort Command Explained
sort arranges lines of text into order. It sounds almost too basic to dedicate an entire article to, but its flags around numeric comparison, specific fields, and combining with other tools come up constantly enough in real shell work to be worth covering properly.
Basic usage
sort names.txt
# alphabetically sorts the lines of names.txt
echo -e "banana\napple\ncherry" | sort
# apple
# banana
# cherry
By default, sort compares lines as plain text, character by character, in what is roughly alphabetical (technically, based on the current locale’s collation rules) order.
The classic numeric sorting problem
echo -e "9\n10\n2\n33" | sort
# 10
# 2
# 33
# 9
This surprises almost everyone the first time they hit it. Without any special flag, sort compares these as plain text, character by character, and the character "1" simply comes before the character "9" in that comparison, regardless of what the numbers actually mean.
echo -e "9\n10\n2\n33" | sort -n
# 2
# 9
# 10
# 33
-n switches to genuine numeric comparison, interpreting each line as a number and ordering by actual numeric value rather than by the text characters that happen to represent it.
Reversing the order
sort -r names.txt
# reverse alphabetical order
sort -rn numbers.txt
# largest number first, instead of smallest
-r reverses whatever ordering would otherwise be applied, and combines cleanly with -n when you specifically want the largest numeric values listed first, a common pattern when looking for the biggest entries in a dataset (largest files, highest counts, and so on).
Sorting by a specific field
cat data.txt
# alice 92 engineering
# bob 78 sales
# carol 85 engineering
sort -k2 -n data.txt
# bob 78 sales
# carol 85 engineering
# alice 92 engineering
-k (key) specifies which whitespace-separated field to sort by, rather than sorting based on the entire line starting from the first character. Here, -k2 sorts by the second column (the numeric score), combined with -n since that column contains numbers rather than text.
sort -t"," -k3 data.csv
-t sets a custom field separator, useful for structured data like CSV files where fields are separated by commas rather than whitespace.
Removing duplicates while sorting
sort -u names.txt
# sorts AND removes exact duplicate lines in one step
-u (unique) combines sorting with duplicate removal, achieving in one command what would otherwise require piping into uniq as a separate step.
Why sort is so often piped into uniq
sort names.txt | uniq
uniq only removes adjacent duplicate lines; if two identical lines are not next to each other in the input, uniq will not catch them at all. Since sorting naturally groups every identical line together as a direct side effect of putting things in order, running sort before uniq guarantees that any duplicates that exist anywhere in the original file end up adjacent by the time uniq sees them, making this combination the standard, reliable way to deduplicate a list.
Case-insensitive sorting
echo -e "banana\nApple\ncherry" | sort
# Apple
# banana
# cherry
# (uppercase A sorts before lowercase letters in default ASCII order)
echo -e "banana\nApple\ncherry" | sort -f
# Apple
# banana
# cherry
# (with -f, case is folded/ignored for comparison purposes)
Without -f, sort order can be affected by the ASCII values of uppercase versus lowercase letters, which can put capitalized words in a different position than a purely alphabetic reading would expect. -f (fold case) treats letters as equivalent regardless of case for sorting purposes.
Sorting by month names or version numbers
sort -M months.txt
# understands month name abbreviations (Jan, Feb, Mar...) and
# sorts them in calendar order rather than alphabetical order
sort -V versions.txt
# understands version number strings like 1.2.10 vs 1.2.9
# and sorts them by version logic (1.2.9 before 1.2.10),
# rather than plain text comparison which would reverse them
-M and -V are specialized comparison modes for two common cases where plain alphabetic or numeric sorting gives the wrong answer: calendar month abbreviations, and software version numbers, both of which have their own specific ordering logic that neither plain text nor pure numeric sort handles correctly on its own.
Frequently Asked Questions
What does the sort command do?
sort reads lines of text, from a file or from piped input, and outputs them rearranged into order, alphabetically by default. It is one of the standard building blocks used throughout shell scripting and command pipelines whenever data needs to be organized before further processing.
Why does sort put “10” before “9” by default, and how do I fix that?
By default, sort compares text alphabetically character by character, so “10” sorts before “9” because the character “1” comes before the character “9”, regardless of the fact that ten is numerically larger than nine. Adding the -n flag switches to proper numeric comparison, so sort -n correctly places 9 before 10, comparing the actual numeric value rather than the text representation.
How do I reverse the sort order?
Add the -r flag, which reverses whatever ordering would otherwise apply, whether alphabetic or numeric. sort -rn on a list of numbers gives the largest value first instead of the smallest, which is a common pattern for quickly finding the biggest values in a dataset.
How do I sort by a specific column or field instead of the whole line?
Use the -k flag followed by the field number, such as sort -k2 data.txt to sort based on the second whitespace-separated field on each line rather than the entire line from the start. A custom field separator can be specified with -t, for example sort -t”,” -k3 data.csv to sort a comma-separated file by its third column.
Why do I often see sort piped into uniq?
uniq only removes ADJACENT duplicate lines, meaning duplicates have to already be next to each other in the input for uniq to catch them. Since sort naturally groups identical lines together as a side effect of ordering them, running sort before uniq (as in sort file.txt | uniq) guarantees that any duplicates in the original file end up adjacent, so uniq can actually find and remove all of them, not just ones that happened to already be next to each other.
How do I sort in a way that ignores case, so “Apple” and “apple” are treated the same?
Add the -f flag (fold case), which makes the comparison case-insensitive for sorting purposes, so “Apple”, “apple”, and “APPLE” are treated as equivalent when determining their relative order, rather than being separated purely based on the ASCII values of uppercase versus lowercase letters.