Using PowerShell, I'm trying to understand the concept of default sort property.
According to this example, provided for the Sort-Object
command :
PS C:\>get-childitem | sort-object
Because no properties are specified, Sort-Object
uses the default sort property for objects of type file
and directory
, which is Name
.
Is there a way to know, for any given type, which is its default sort property ?
In JavaScript, we use the sort() function to sort an array of objects. The sort() function is used to sort the elements of an array alphabetically and not numerically. To get the items in reverse order, we may use the reverse() method.
The Sort-Object cmdlet sorts objects in ascending or descending order based on object property values. If sort properties are not included in a command, PowerShell uses default sort properties of the first input object.
To sort the output in the PowerShell you need to use Sort-Object Pipeline cmdlet. In the below example, we will retrieve the output from the Get-Process command and we will sort the, according to memory and CPU usage.
To sort a hashtable, use the GetEnumerator() method on the hashtable to gain access to its individual elements. Then use the SortObject cmdlet to sort by Name or Value.
In my understanding the default property is taken from the .ps1XML
file for the predefined types. But I found nothing about that in about_Format.PS1XML
The default sort property is defined in the types.ps1xml file (in the $PSHOME
directory). From the online help for Sort-Object
:
The Sort-Object cmdlet sorts objects based on properties specified in the command or the default sort properties for the object type. Default sort properties are defined using the PropertySet named DefaultKeyPropertySet in a types.ps1xml file. For more information, see about_Types.ps1xml.
You can update the DefaultKeyPropertySet value for the current session using Update-TypeData
. I've provided a couple of examples below.
Note: in these examples Sort-Object
is being applied before Select-Object
so that sorting is applied to the objects coming out of Get-ChildItem
rather than those coming out of Select-Object
.
Update with command parameters
This technique only allows setting the values once per session.
# Inspect the current sort properties: not set
PS C:\Test>Get-TypeData -TypeName System.IO.FileInfo | Select-Object -ExpandProperty DefaultKeyPropertySet
# See Get-ChildItem results before a change is made: sorting on name
PS C:\Test>Get-ChildItem -File | Sort-Object | Select-Object FullName,CreationTime
FullName CreationTime
-------- ------------
C:\Test\A.txt 18-Apr-2021 17:09:22
C:\Test\B.txt 10-Apr-2021 19:44:59
C:\Test\C.txt 31-Mar-2021 12:53:01
# Update the sort properties
PS C:\Test>Update-TypeData -TypeName 'System.IO.FileInfo' -DefaultKeyPropertySet 'CreationTime','FullName'
PS C:\Test>Get-TypeData -TypeName System.IO.FileInfo | Select-Object -ExpandProperty DefaultKeyPropertySet
ReferencedProperties IsHidden
-------------------- --------
{CreationTime, FullName} False
# See the results after a change is made: sorting on creation time
PS C:\Test>Get-ChildItem -File | Sort-Object | Select-Object FullName,CreationTime
FullName CreationTime
-------- ------------
C:\Test\C.txt 31-Mar-2021 12:53:01
C:\Test\B.txt 10-Apr-2021 19:44:59
C:\Test\A.txt 18-Apr-2021 17:09:22
# Update the sort properties again: error
PS C:\Test>Update-TypeData -TypeName 'System.IO.FileInfo' -DefaultKeyPropertySet 'FullName','CreationTime'
Update-TypeData : Error in TypeData "System.IO.FileInfo": The member DefaultKeyPropertySet is already present.
At line:1 char:1
+ Update-TypeData -TypeName 'System.IO.FileInfo' -DefaultKeyPropertySet ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Update-TypeData], RuntimeException
+ FullyQualifiedErrorId : TypesDynamicUpdateException,Microsoft.PowerShell.Commands.UpdateTypeDataCommand
Update with custom xml file
This technique allows setting the values multiple times per session. With an xml file, types_test.ps1xml, containing the following:
<?xml version="1.0" encoding="utf-8" ?>
<Types>
<Type>
<Name>System.IO.FileInfo</Name>
<Members>
<MemberSet>
<Name>PSStandardMembers</Name>
<Members>
<PropertySet>
<Name>DefaultKeyPropertySet</Name>
<ReferencedProperties>
<Name>CreationTime</Name>
<Name>FullName</Name>
</ReferencedProperties>
</PropertySet>
</Members>
</MemberSet>
</Members>
</Type>
</Types>
# Inspect the current sort properties: not set
PS C:\Test>Get-TypeData -TypeName System.IO.FileInfo | Select-Object -ExpandProperty DefaultKeyPropertySet
# See Get-ChildItem results before a change is made: sorting on name
PS C:\Test>Get-ChildItem -File | Sort-Object | Select-Object FullName,CreationTime
FullName CreationTime
-------- ------------
C:\Test\A.txt 18-Apr-2021 17:09:22
C:\Test\B.txt 10-Apr-2021 19:44:59
C:\Test\C.txt 31-Mar-2021 12:53:01
# Update the sort properties
PS C:\Test>Update-TypeData -PrependPath 'D:\types_test.ps1xml'
PS C:\Test>Get-TypeData -TypeName System.IO.FileInfo | Select-Object -ExpandProperty DefaultKeyPropertySet
ReferencedProperties IsHidden
-------------------- --------
{CreationTime, FullName} False
# See the results after a change is made: sorting on creation time
PS C:\Test>Get-ChildItem -File | Sort-Object | Select-Object FullName,CreationTime
FullName CreationTime
-------- ------------
C:\Test\C.txt 31-Mar-2021 12:53:01
C:\Test\B.txt 10-Apr-2021 19:44:59
C:\Test\A.txt 18-Apr-2021 17:09:22
# In types_test.ps1xml, switch the order of the elements under the <ReferencedProperties> tag
# Update the sort properties again:
PS C:\Test>Update-TypeData -PrependPath 'D:\types_test.ps1xml'
PS C:\Test>Get-TypeData -TypeName System.IO.FileInfo | Select-Object -ExpandProperty DefaultKeyPropertySet
ReferencedProperties IsHidden
-------------------- --------
{FullName, CreationTime} False
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With