Order Your Output by Easily Sorting Objects in PowerShell

Summary: Much of the time, there is no guarantee to the order in which Windows PowerShell returns objects. This blog explains how to fix that issue.

Hey, Scripting Guy! I have a problem with Windows PowerShell. It seems that it deliberately randomizes the output. I mean, there seems to be no rhyme or reason to the way that information is returned from a cmdlet. Am I alone in this frustration, or is there some secret sauce that I am missing? Windows PowerShell is cool, but if I always have to put data into an Excel spreadsheet just to sort it, then it is not much better than VBScript in my mind. Help me, oh fount of Windows PowerShell wisdom.

—CD

Hello CD,

Microsoft Scripting Guy, Ed Wilson, is here. The other day, the Scripting Wife and I were at the first ever Windows PowerShell User Group meeting in Charlotte, North Carolina. It was really cool. We love being able to interact with people who love Windows PowerShell as much as we do. Next month, we are having a script-club type of meeting; we encourage people to show up with the Windows PowerShell scripts they are working on, so it will be a show-and-tell type of meeting.

Use Sort-Object to organize output

Anyway, after the user group meeting, when we were all standing around, one of the attendees came up to me and asked me in what order Windows PowerShell returns information. The answer is that there is no guarantee of return order in most cases. The secret sauce is to use the built-in sorting mechanism from Windows PowerShell itself. In the image that follows, the results from the Get-Process cmdlet appear to sort on the ProcessName property.

One could make a good argument that the processes should sort on the process ID (PID) or on the amount of CPU time consumed, or on the amount of memory utilized. In fact, it is entirely possible that for each property supplied by the Processobject, someone has a good argument for sorting on that particular property. Luckily, custom sorting is easy to accomplish in Windows PowerShell. To sort returned objects in Windows PowerShell, pipe the output from one cmdlet to the Sort-Object cmdlet. This technique is shown here where the Sort-Object cmdlet sorts the Processobjects that are returned by the Get-Process cmdlet.

Get-Process | Sort-Object id

The command to sort the Processobjects on the ID property and the output associated with that command are shown in the image that follows.

Reversing the sort order

By default, the Sort-Object cmdlet performs an ascending sort—the numbers range from small to large. To perform a descending sort requires utilizing the Descendingswitch.

Note: There is no Ascendingswitch for the Sort-Object cmdlet because that is the default behavior.

To arrange the output from the Get-Process cmdlet such that the Processobjects appear from largest process ID to the smallest (the smallest PID is always 0—the Idle process), choose the IDproperty to sort on, and use the Descendingswitch as shown here:

Get-Process | Sort-Object id –Descending

The command to perform a descending sort of processes based on the process ID, and the output associated with that command are shown in the image that follows.

When you use the Sort-Object cmdlet to sort output, keep in mind that the first position argument is the property or properties upon which to sort. Because Propertyis the default means that using the name Propertyin the command is optional. Therefore, the following commands are equivalent:

Get-Process | Sort-Object id –Descending

Get-Process | Sort-Object -property id –Descending

In addition to using the default first position for the Propertyargument, the Sort-Object cmdlet is aliased by sort. Byusing gpsas an alias for the Get-Process cmdlet, sortas an alias for Sort-Object, and a partial parameter of desfor Descending, the syntax of the command is very short. This short version of the command is shown here.

gps | sort id –des

Sorting multiple properties at once

The Propertyparameter of the Sort-Object cmdlet accepts an array (more than one) of properties upon which to sort. This means that I can sort on the process name, and then sort on the working set of memory that is utilized by each process (for example). When supplying multiple property names, the first property sorts, then the second property sorts.

The resulting output may not always meet expectations, and therefore, may require a bit of experimentation. For example, the command that follows sorts the process names in a descending order. When that sort completes, the command does an additional sort on the WorkingSet (ws is the alias) property. However, this second sort is only useful when there happen to be multiple processes with the same name (such as the svchostprocess). The command that is shown here is an example of sorting on multiple properties.

Get-Process | Sort-Object -Property name, ws –Descending

The figure that is shown here illustrates the output from the command to sort Processobjects based on name and wsproperties.

When the name and wsproperties reverse order in the command, the resulting output is not very useful because the only sorting of the nameproperty happens when multiple processes have an identical working set of memory. The command that is shown here reverses the order of the WorkingSet and the process name properties.

Get-Process | Sort-Object -Property ws, name –Descending

The output that is shown here shows that there is very little grouping of process names. In this example, adding the nameproperty does not add much value to the command.

Sorting and returning unique items

At times, I might want to see how many different processes are running on a system. To do this, I can filter duplicate process names by using the Uniqueswitch. To count the number of unique processes that are running on a system, I pipe the results from the Sort-Object cmdlet to the Measure-Object cmdlet. This command is shown here.

This sorting is great, but I’m curious how Powershell sorts properties of a single object. That too seems entirely random and further there seems to be no way to sort by property name. Any idea why?

For example: Get-Process System | fl *

Notice the resulting properties just display in seemingly random order. I’ve found ways to actually sort these properties by loading them into a sorted string array and passing those array members to the FL command, but that’s extremely cumbersome.

Why does Powershell not offer a native way to sort by property? And what is the significance of the default sort order?