Skip to content
shellmap

Sort a file by a specific column

Sort lines of a file by the value in a chosen column (numeric or alphabetic).

How to sort a file by a specific column in each shell

Bashunix
sort -t, -k3 -n file.csv

`-t,` field delimiter (comma), `-k3` sort key = column 3 (1-indexed), `-n` numeric. For multi-column: `-k3,3 -k1,1` (sort by col 3, ties broken by col 1). For descending: `-rn`. For column-range: `-k3.2,3.5` (chars 2–5 of column 3). For TAB delimiter you need a LITERAL tab: `sort -t$'\t' -k2 file.tsv` (`$'\t'` is bash ANSI-C quoting).

Zshunix
sort -t, -k3 -n file.csv

Same external `sort`. macOS BSD `sort` is mostly compatible — but `--field-separator` (long flag) is GNU-only. `-h` (human-readable suffixes: K/M/G) works on both macOS Sonoma+ and GNU. macOS `sort` does NOT have `--debug` (GNU-only — shows which characters of the line are the sort key — extremely useful for "why is this row in the wrong position" mysteries).

Fishunix
sort -t, -k3 -n file.csv

Same external `sort`. Fish has no `$'\t'` equivalent — for TAB delimiter: `sort -t (printf '\t') -k2 file.tsv`.

PowerShellwindows
Import-Csv file.csv | Sort-Object -Property {[double]$_.Price}

`Sort-Object -Property` accepts a column name (`Sort-Object -Property Price`) or a script block (`{[double]$_.Price}` casts string→double for numeric sort — without the cast `"10"` sorts before `"9"` because string-compare). `-Descending`, `-Unique` modifiers. For CSV-with-quoted-fields, `Import-Csv` correctly handles RFC 4180; `Get-Content | ForEach-Object { ($_ -split ",")[2] }` does NOT (breaks on commas inside quoted fields).

cmd.exewindows
powershell -Command "Import-Csv file.csv | Sort-Object Price | ConvertTo-Csv"

`sort` (cmd builtin) sorts WHOLE LINES alphabetically — no column support. `sort /+N file.txt` sorts starting at character POSITION N (not column N — totally different). For column-by-CSV: shell out to pwsh. `findstr /R` can FILTER by column-shaped patterns but not sort.

Equivalents listed for Bash, Zsh, Fish, PowerShell, cmd.exe.

Gotchas & notes

  • **Numeric vs lexicographic — `-n` matters**: without `-n`, `sort` does CHARACTER-by-character comparison: `10` sorts BEFORE `9` (because `'1' < '9'`). With `-n`, `9` sorts before `10` (numeric). Mixed-content columns (`v9` vs `v10`) need `-V` (version sort): `v9 < v10 < v11`. `sort -h` handles human-readable suffixes: `1K < 2K < 1M < 1G`. Pick the right flag for the data type — wrong flag silently produces wrong output.
  • **Stable sort — `-s` flag**: by default GNU `sort` is NOT stable (ties may be reordered). `sort -s` enables stable sort — keys with equal sort-values preserve their input order. Critical for multi-pass sorts: `sort -k3 -s | sort -k1 -s` correctly sorts by col 1 with col 3 as tiebreaker. Without `-s`, the col-3 ordering within col-1 ties is randomized.
  • **Locale affects ordering**: `sort` honors `LC_ALL` / `LC_COLLATE`. `LC_ALL=en_US.UTF-8 sort` may sort with locale-specific rules (`a`, `A`, `á`, `B`, `b` collation order). `LC_ALL=C sort` uses byte-ordering — ASCII-sane, fastest, and reproducible across machines. For scripts that must be deterministic across systems: prefix every `sort` invocation with `LC_ALL=C`. Production data pipelines have been broken by Ubuntu→Alpine container moves where the default locale changed.
  • **pwsh ordering on mixed types**: `Sort-Object` compares using each property's natural type — but a CSV column is ALL STRINGS by default (string `"10"` < `"9"` lexicographically). Cast in a script block: `{[double]$_.Amount}` or `{[int]$_.Count}`. For DATE-typed sort on a string column: `{[datetime]$_.Timestamp}`. Without casting, you'll get string-sort surprises every time.

Related commands

Related tasks