Jump to page sections
If you have a list of computers from different domains, you might want to sort them by domain first and then the computer name. Here is how.

The method I use, is simply stripping off the host name - which I define as anything before the first dot (plus the first dot, but that doesn't really matter) - sorting by what's left, which is the domain, then sorting secondarily on just the host name, which I conveniently get by using the System.String class' Split() method on a period to extract what's before the first period in the string. It works. Actually, just using "Expression = { $_ }" will work too for the secondary sort criteria. That's essentially what I do in the example with a property.

This will work with PowerShell version 2 and up.

Sorting computer names when you have strings

I put a bunch of fake hosts and domains in an array, and then demonstrate how to sort it by domain first and then by host name / computer name (anything real under these domains is unknown to me!).


The same example, as text, for pasty delightfulness:

PS C:\> $Servers = @('host05.aaa.com', 'hostX.zzz.com', 'host10.bbb.com', 'host08.bbb.com',
    'host06.ccc.com', 'host99.aaa.com', 'host00.ccc.com', 'host01.aaa.com')
$Servers | Sort-Object @{ Expression = { $_ -replace '^[^.]+\.' } }, @{ Expression = { $_.Split('.')[0] } }

host01.aaa.com
host05.aaa.com
host99.aaa.com
host08.bbb.com
host10.bbb.com
host00.ccc.com
host06.ccc.com
hostX.zzz.com

Sorting computer names when you have an object with a string property

When you use Get-ADComputer, you get a DNSHostName property back. Here I use the same list of servers as in the example above, create custom PS objects (in a v2-compatible way) that have a DNSHostName as a string property, and then sort by domain and name. The sorting is actually easier, or at least less typing, this way.


And again, as text, for pasting, and for the visually impaired:

PS C:\> $ServerObj = $Servers | foreach {
    New-Object PSObject -Property @{
        DNSHostName = $_
        #ComputerName = $_.Split('.')[0]
    }
}

$ServerObj | Sort-Object @{ Expression = { $_.DNSHostName -replace '^[^.]+\.' } }, DNSHostName |
    Format-Table -AutoSize

DNSHostName   
-----------   
host01.aaa.com
host05.aaa.com
host99.aaa.com
host08.bbb.com
host10.bbb.com
host00.ccc.com
host06.ccc.com
hostX.zzz.com 

Sorting computer names with numbers zero-padded

What if some despicable non-programmer decided to use the nomenclature "server1", "server2", "server3", etc. without padding with zeroes? Now your sorting is all whacked with 1, 10, 11, 12 ... 19, 2, 20, 21, 22 ... and so on.

Me to the rescue! I even handle multiple levels of nesting in non-zero-padded numbers. By the way, that will also work for IPv4 addresses, if you modify it slightly and run it against the entire string by removing the ".Split()" method call, as an added bonus.

PS C:\> $Servers = @('host5.aaa.com', 'host00.zzz.com', 'host11a2.aaa.com', 'host11a11.aaa.com',
    'host11a3.aaa.com', 'host11a10.aaa.com', 
    'host11.aaa.com', 'host1.aaa.com', 'host10.aaa.com', 'host2.aaa.com')

$Servers | Sort-Object @{ Expression = { $_ -replace '^[^.]+\.' } },
    @{ Expression = { [regex]::Replace($_.Split('.')[0], '(\d+)', { '{0:D16}' -f [int] $args[0].Value }) } },
    @{ Expression = { $_ } }

host1.aaa.com
host2.aaa.com
host5.aaa.com
host10.aaa.com
host11.aaa.com
host11a2.aaa.com
host11a3.aaa.com
host11a10.aaa.com
host11a11.aaa.com
host00.zzz.com

Nested domains / subdomains

As someone helpfully commented on Reddit, you could want to sort the subdomains as well.

That can be accomplished like this:

$Servers | 
    Sort-Object @{Expression = {
        $TemporaryArray = @($_.Split('.'))
        [Array]::Reverse($TemporaryArray)
        $TemporaryArray
    }}

                                            
b                                           
a.b                       
a.com    
host01.aaa.com
host05.aaa.com
host99.aaa.com
host00.bbb.com
host08.bbb.com
host10.bbb.com
c.com
c.c.com
host00.ccc.com
host06.ccc.com
hostX.zzz.com
a.d

Or, if you don't want to mix the subdomains with the host names, you could repeat it by first sorting one level up.

$Servers | Sort-Object @{Expression = {
    $TemporaryArray = @(([String]($_.Split('.', 2)[1])).Split('.'))
    [Array]::Reverse($TemporaryArray)
    $TemporaryArray
    }},
    @{Expression = {
        $TemporaryArray = @($_.Split('.'))
        [Array]::Reverse($TemporaryArray)
        $TemporaryArray
    }}

b
a.b
a.com
c.com
host01.aaa.com
host05.aaa.com
host99.aaa.com
host00.bbb.com
host08.bbb.com
host10.bbb.com
c.c.com
host00.ccc.com
host06.ccc.com
hostX.zzz.com
a.d
Powershell      Windows      Regex          All Categories

Google custom search of this website only

Minimum cookies is the standard setting. This website uses Google Analytics and Google Ads, and these products may set cookies. By continuing to use this website, you accept this.

If you want to reward my efforts