A disk is filling up and you need to know which files are eating it. Or a log folder has 400 files and you want the newest one. Explorer can sort a column, but it can't sort by two things at once, it can't cut the list to the top 10, and it can't hand that list to the next command. Sort-Object can.
The one-liner that answers "what's taking all the space?"
Get-ChildItem -File | Sort-Object Length -Descending | Select-Object -First 10 Name, Length
What happens here:
-
Get-ChildItem -Filesends file objects down the pipeline.-Fileskips folders, which matters (see the traps below). -
Sort-Object Lengthsorts by theLengthproperty, which is the size in bytes. It compares numbers, not text. -
-Descendingputs the biggest first. Without it you get the smallest first, which is rarely what you want at 2 a.m. -
Select-Object -First 10keeps the top ten and shows only the two columns you care about.
Swap Length for LastWriteTime or Name and the same line sorts by date or name. That's the whole idea: pick a property, pick a direction, cut the list.
Recipe 1: newest files first
Get-ChildItem C:\Logs -File | Sort-Object LastWriteTime -Descending | Select-Object -First 5
LastWriteTime is a real DateTime, so you get true chronological order. No guessing whether 01/02 means January or February.
Need just the single newest file to open it?
$latest = Get-ChildItem C:\Logs\*.log | Sort-Object LastWriteTime | Select-Object -Last 1
notepad $latest.FullName
Recipe 2: top 10 largest files on a whole tree, in MB
Get-ChildItem D:\Shares -File -Recurse -ErrorAction SilentlyContinue |
Sort-Object Length -Descending |
Select-Object -First 10 FullName, @{ Name = 'MB'; Expression = { [math]::Round($_.Length / 1MB, 1) } }
The @{ Name = ...; Expression = ... } part is a calculated property. It turns raw bytes into something a human can read without changing what you sorted on. -ErrorAction SilentlyContinue keeps "access denied" folders from flooding the screen.
On PowerShell 7 you can skip Select-Object -First and use Sort-Object Length -Top 10, which is shorter and avoids sorting the entire list in memory just to keep ten rows.
Recipe 3: sort by two properties at once
Get-ChildItem -File | Sort-Object Extension, Length
Files are grouped by extension first (.csv, then .log, then .zip), and inside each group they're ordered by size. This is the thing Explorer can't do.
Want the groups in A to Z order but the biggest file first inside each group? Use hashtables to set the direction per property:
Get-ChildItem -File | Sort-Object @{ Expression = 'Extension'; Descending = $false },
@{ Expression = 'Length'; Descending = $true }
Recipe 4: keep the newest 5 backups, delete the rest
This is where sorting stops being cosmetic and starts doing ops work:
Get-ChildItem D:\Backups\*.bak |
Sort-Object LastWriteTime -Descending |
Select-Object -Skip 5 |
Remove-Item -WhatIf
Sort newest first, skip the five you want to keep, delete everything else. -WhatIf prints what would be removed. Read that list carefully, then run the same line without -WhatIf. Drop this into a scheduled task and you have backup rotation in four lines.
Three traps worth knowing
- Numbers stored as text sort like text. If you read values from a CSV or a file name, they're strings, and strings sort character by character:
'9', '10', '100' | Sort-Object
# 10, 100, 9
Cast inside a script block to sort them as numbers:
'9', '10', '100' | Sort-Object { [int]$_ }
# 9, 10, 100
The same thing bites with names like log1.txt, log10.txt, log2.txt. Pad numbers with zeros when you create files (log001.txt) and the problem never shows up.
Name sorting depends on culture.
Sort-Objectuses your current culture and ignores case by default. On a Czech system,chis a separate letter that sorts afterh, sochyba.txtlands afterhosts.txt. If a script must produce the same order on every machine, say so explicitly withSort-Object Name -Culture 'en-US'or add-CaseSensitivewhen case matters.NamevsFullNameon recursive listings. With-Recurse,Sort-Object Namemixes files from every folder into one alphabetical list, so twoconfig.jsonfiles from different projects end up next to each other with no hint of where they live. Sort byFullNameto keep each folder's files together, or byDirectoryName, Nameto make that grouping explicit.
Bonus trap: folders have no Length property. If you forget -File, all the folders bunch up at one end of a size sort and look like zero-byte files.
Why the pipeline version beats clicking column headers
Explorer's column sort is fine for a glance. But it can't combine two sort keys, it can't stop at the top 10, it can't recurse a whole share into one list, and it can't pass the result on to Remove-Item, Copy-Item or Export-Csv. Sort-Object sits in the middle of a pipeline, so the answer to "which files?" becomes the input to "now do something with them". Once that clicks, you stop sorting to look and start sorting to act.
Practice it without touching real files
Recipe 4 deletes things, so it's worth getting the pipeline right somewhere safe first. In CMD Master's interactive PowerShell lessons you can practice Get-ChildItem, Sort-Object and the rest of the pipeline in a live browser terminal with instant feedback, no install and no VM. The same free command line learning platform also covers Windows CMD and Bash if you switch between systems.
Your turn: what do you sort by most often, size, date, or something weirder? Drop your favorite Sort-Object line in the comments.
Top comments (0)