Skip to content

/commands/coreutils/sort-by-column

sort -k: sort a file by a column (numeric, reverse, by delimiter)

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · ls (GNU coreutils) 8.32updated
tool
GNU coreutils
versions
GNU coreutils 8.x, GNU coreutils 9.x
os
linux, macos, windows

sort -k2,2 file sorts lines by the second whitespace-separated column; add n for numbers (-k2,2n), r for descending order (-k2,2nr), and -t, to split on commas instead of blanks (sort -t, -k3,3n data.csv). Always give the key an end (,2): -k2 alone means "from field 2 to the end of the line". Several -k options set tie-breakers, applied left to right.

Examples

bash
cat > people.csv <<'EOF'
name,team,age
ada,core,36
bob,web,41
cyd,core,29
dan,web,9
EOF
tail -n +2 people.csv | sort -t, -k3,3n
echo ---
tail -n +2 people.csv | sort -t, -k3,3
echo ---
tail -n +2 people.csv | LC_ALL=C sort -t, -k2,2 -k3,3nr

Output

dan,web,9
cyd,core,29
ada,core,36
bob,web,41
---
cyd,core,29
ada,core,36
bob,web,41
dan,web,9
---
ada,core,36
cyd,core,29
bob,web,41
dan,web,9

The first sort is numeric, so 9 comes before 29. The second compares the ages as text, character by character, so 9 sorts after 41. The third sorts by team, and inside each team by age in descending order: the r applies only to that key.

Key syntax

OptionMeaning
-k2,2Key is field 2 only
-k2Key runs from field 2 to the end of the line
-k2,2nField 2 compared as a number (leading blanks, sign and decimals understood)
-k2,2nrSame, descending
-k1.3,1.5Characters 3 to 5 of field 1
-t,Fields separated by a comma; default is the change from non-blank to blank
-n / -r / -hGlobal numeric, reverse, human sizes (2K, 1G) when no key has its own letters
-VVersion order: 1.9 before 1.10 (GNU)
-sStable: lines with equal keys keep their input order
-uPrint only the first of each run of lines with equal keys
-o FILEWrite the result to FILE, which may be the input file itself

Sort human-readable sizes

bash
printf '%s\n' '1.5G backups' '200K notes' '12M photos' '900M videos' > sizes.txt
sort -h sizes.txt
sort -hr sizes.txt | head -n 2

Output

200K notes
12M photos
900M videos
1.5G backups
1.5G backups
900M videos

-h understands the suffixes printed by du -h and ls -lh, so du -sh * | sort -h lists directories from smallest to largest.

Pitfalls

  • sort file > file empties the file, because the shell truncates it before sort reads it. Use sort -o file file.
  • Blank-separated fields keep their leading blanks with the default separator. Text keys on padded input can then sort oddly; add b to the key (-k2,2b) or use -t with a real delimiter.
  • Quoted CSV fields with commas are split at every comma: sort -t, does not understand CSV quoting. Use a CSV-aware tool for such files.
  • macOS and BSD sort accept the same -k, -t, -n, -r, -h and -V options on current releases; GNU-only options such as --parallel differ.

Confirm the result

sort -c -t, -k3,3n file checks whether a file is already sorted by that key and prints the first line out of order (sort: file:3: disorder: ...) with exit status 1, or stays silent with status 0.

FAQ

Why does sort -k2 not sort by the second column only?

-k2 means a key from field 2 to the end of the line, so later fields take part in the comparison. Write -k2,2 to stop the key at field 2, and add the type letter to it, -k2,2n for numbers.

How do I sort a CSV but keep the header line on top?

Print the header first and sort the rest, for example (head -n 1 data.csv; tail -n +2 data.csv | sort -t, -k3,3n) > sorted.csv. sort has no option to skip a header.

Why does sort give a different order on another machine?

sort follows the locale's collation rules, which ignore case and punctuation in many UTF-8 locales. Set LC_ALL=C for byte order, which is the same everywhere and faster.

Sources