/commands/coreutils/sort-by-column
sort -k: sort a file by a column (numeric, reverse, by delimiter)
- 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
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,3nrOutput
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
| Option | Meaning |
|---|---|
| -k2,2 | Key is field 2 only |
| -k2 | Key runs from field 2 to the end of the line |
| -k2,2n | Field 2 compared as a number (leading blanks, sign and decimals understood) |
| -k2,2nr | Same, descending |
| -k1.3,1.5 | Characters 3 to 5 of field 1 |
| -t, | Fields separated by a comma; default is the change from non-blank to blank |
| -n / -r / -h | Global numeric, reverse, human sizes (2K, 1G) when no key has its own letters |
| -V | Version order: 1.9 before 1.10 (GNU) |
| -s | Stable: lines with equal keys keep their input order |
| -u | Print only the first of each run of lines with equal keys |
| -o FILE | Write the result to FILE, which may be the input file itself |
Sort human-readable sizes
printf '%s\n' '1.5G backups' '200K notes' '12M photos' '900M videos' > sizes.txt
sort -h sizes.txt
sort -hr sizes.txt | head -n 2Output
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 > fileempties the file, because the shell truncates it before sort reads it. Usesort -o file file.- Blank-separated fields keep their leading blanks with the default separator. Text keys on padded input can then sort oddly; add
bto the key (-k2,2b) or use-twith 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,-hand-Voptions on current releases; GNU-only options such as--paralleldiffer.
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.