Working with Sort-Object Cmdlet

In this blog I will try to explain different features of sort-object(Sort) cmdlet. For the purpose of this blog, I assume the following objects exist:

 

MSH C:\temp\monad> $a,$b,$c,$d

 

                                  Score Name

                                  ----- ----

                                    100 John

                                     90 Henry

                                     90 Tom

                                     80 David

 

 

From the definition Sort looks like:

 

MSH C:\temp\monad> (get-command sort-object).Definition

sort-object [[-Property] Object[]] [-Descending] [-Unique] [-InputObject MshObj

ect] [-Culture String] [-CaseSensitive] [-Verbose] [-Debug] [-ErrorAction Actio

nPreference] [-ErrorVariable String] [-OutVariable String] [-OutBuffer Int32]

 

The basic usage looks like:

 

<expression> | sort <property>

 

Sort works on a collection of input objects possibly coming over from a pipeline. Sort will collect all the input objects from the pipeline and then sorts the objects based on other parameters like Property, Descending, Unique etc.

 

Example: To sort objects based on Score

 

MSH C:\temp\monad> $a,$b,$c,$d | sort score

 

                                  Score Name

                                  ----- ----

                                     80 David

                                     90 Tom

                                     90 Henry

                                    100 John

 

Example: To sort objects based on Name

 

MSH C:\temp\monad> $a,$b,$c,$d | sort Name

 

                                  Score Name

                                  ----- ----

                                     80 David

                                     90 Henry

                                    100 John

                                     90 Tom

 

Example: To sort objects in descending order based on Score

 

MSH C:\temp\monad> $a,$b,$c,$d | sort Score -Descending

 

                                  Score Name

                                  ----- ----

                                    100 John

                                     90 Tom

                                     90 Henry

                                     80 David

 

Ok, this is all simple and you might yourself have already explored all this. Let us get into some tricky stuff. How to sort on Score (descending order) and Name (ascending order)

 

Example: sort on Score descending and then Name ascending

 

 

MSH C:\temp\monad> $a,$b,$c,$d | sort @{expression="Score";Descending=$true},@{e

xpression="Name";Ascending=$true}

 

                                  Score Name

                                  ----- ----

                                    100 John

                                     90 Henry

                                     90 Tom

                                     80 David

 

Notice the use of @{expression=…}. If you notice the definition of sort-object, the parameter Property takes in a object[].  Property parameter can take entries of form <string> or hashtable (notice @). If the input is a hashtable, then Sort cmdlet specifically looks for “expression”,”ascending”,”descending” keys. Ascending and Descending can take only Booleans ( i.e., $true or $false ). Using expression you can do many things.

 

For example, lets say Henry is very punctual and very dedicated and you wanted to give some additional marks (lets say 2 marks) to encourage him.

 

Example:

 

MSH C:\temp\monad> $a,$b,$c,$d | sort @{expression={if ($_.Name -eq "Henry") { $

_.Score += 2 }}},Score -Descending

 

                                  Score Name

                                  ----- ----

                                    100 John

                                     92 Henry

                                     90 Tom

                                     80 David

 

Notice the use of Script for expression. In the above example, I changed the original object itself by using $_ and then sorted on Score

 

MSH C:\temp\monad> $b

 

                                  Score Name

                                  ----- ----

                                     92 Henry

 

Using Script block you can do many things like computing Grades and then sorting on Grade.

 

MSH C:\temp\monad> $a,$b,$c,$d | sort Grade,@{expression={if ($_.Score -gt 91) {

$Grade="A" } else {$Grade="B" }; add-member noteproperty "Grade" $Grade -InputOb

ject $_}} -Descending

 

                     Score Name                       Grade

                     ----- ----                       -----

                        90 Tom                        B

                        80 David                      B

                       100 John                       A

                        92 Henry                      A

 

Sort in its simplest form is very useful. Using expressions effectively makes it more powerful.

 

One last thing, a number of you has asked how to sort a hashtable using Sort-Object cmdlet.

 

MSH C:\temp\monad> $hash=@{"Tom"=90;"Henry"=90;"David"=80;"John"=100}

MSH C:\temp\monad> $hash | sort value -descending

 

Name                           Value

----                           -----

Henry                          90

Tom                            90

David                          80

John                           100

This will not work as there is only one object on the pipeline and sort-object does not have anything to sort. However use GetEnumerator() on HashTable to write all the hash entries to the pipeline and then use sort.

 

MSH C:\temp\monad> $hash.GetEnumerator() | sort value -descending

 

Name                           Value

----                           -----

John                           100

Tom                            90

Henry                          90

David                          80

 

-Krishna[MSFT]

Comments

  • Anonymous
    March 21, 2006
    Shoot, now you tell me I can sort by multiple properties!  That could have saved me a bit of code in my WTT script.

    Seriously, thanks for the info!  Very useful.