Compare-Object

Depending on what tasks you perform with PowerShell, you may never need Compare-Object. However, when you need it, you will find it immensely helpful and problematic at the same time. For this PowerShell Tip of the Week we will go over what the purpose of the cmdlet is, some real world examples and ways to handle its output with other cmdlets…

Compare-Object

[sourcecode language=”powershell”]
Get-Help Compare-Object -Examples
[/sourcecode]

And for reference, here is the Syntax for the cmdlet:


Let’s take some sample data sets, ones that may occur in the real world, but are more in line with test data sets. Using data like this will help us get a feel for how Compare-Object works.
[sourcecode language=”powershell”]
$Test = '1','2','3','4','5'
$Test2 = '3','5','6','7','8'
[/sourcecode]
We then use Compare-Object to look at both data sets with respect to each other:
[sourcecode language=”powershell”]
Compare-Object $Test $Test2
[/sourcecode]
Here is the Output:


How do we interpret these results? We see that there are indicators pointing to the left (‘<=') and to the right ('=>‘), but what does this mean? Well, Compare-Object, by default is showing the differences between the two items so the arrows point to the dataset where the ‘InputObject’ is contained. In our case, the $Test array is on the left side and $Test2 is on the right side (order of how they were provided to the Compare-Object cmdlet. So if we switched this order, then we should get arrows in the opposite direction.
[sourcecode language=”powershell”]
Compare-Object $Test2 $Test
[/sourcecode]

While the InputObjects are in a different order, we can indeed see that the indicators are pointed in the opposite direction. Now, if we want, we can exclude all the differences and show just what is the same between the two or see all indicators.

Show all values
[sourcecode language=”powershell”]
Compare-Object $Test2 $Test -IncludeEqual
[/sourcecode]
Show just equal values:
[sourcecode language=”powershell”]
Compare-Object $Test2 $Test -IncludeEqual -ExcludeDifferent
[/sourcecode]
For fun, if you want to eliminate all results, just run this:
[sourcecode language=”powershell”]
Compare-Object $Test2 $Test -ExcludeDifferent
[/sourcecode]
That is pretty useless, but at least you would understand why and not to use these two switches together.

Real World Example 1

In this real world example we are trying to identify Distribution Groups that are not active any more so we can perform some action to them (out of scope of this blog article). With the script we are able to get a list of all distribution groups and we store those groups in a variable called $AllGroups. We then are able to pull a list of active groups (looking at mail activity) and we store these groups in a variable called $ActiveGroups. How can we determine which groups are inactive? By using Compare-Object to see which groups are in $AllGroups and not in $ActiveGroups. We can then store the results into a variable called $InactiveGroups.

** Note that all the variables are named in such a way that others who did not write the script may be able to read it and determine the variable’s purpose in the script

So how do we actually use the Compare-Object to perform our actions? Let’s start with the data.
For this example, let’s say we were able to confirm that our variables did contain the right data something like this:
[sourcecode language=”powershell”]
$ActiveGroups = 'Group1','Group5','Group7'
$AllGroups = 'Group1','Group2','Group3','Group4','Group5','Group6','Group7','Group8','Group9','Group10'
[/sourcecode]
If we were to run our comparison, like this:
[sourcecode language=”powershell”]
Compare-Object $ActiveGroups $AllGroups
[/sourcecode]
Then we would see these results:

Notice that the groups indicated above are all pointing to the right, which is where the $AllGroups variable was AND are not in the $ActiveGroups variable. So these are indeed our inactive groups. Now let’s store this new list with a variable like so:
[sourcecode language=”powershell”]
$InactiveGroups = Compare-Object $ActiveGroups $AllGroups
[/sourcecode]
If we examine the contents of the $InactiveGroups variable we see the same things as the previous comparison:

Which is not ideal. Now how do we handle this?
[sourcecode language=”powershell”]
Foreach ($InactiveGroup in $InactiveGroupss) {
    $Group = $InactiveGroup.inputobject
    $AllInactiveGroups += $Group
}
[/sourcecode]
We can then see that our new variable, $AllInactiveGroups, contains those inactive group names:

From here we can now process this list of groups however we need.

Conclusion

As we can see in the above example, the Compare-Object cmdlet allows us to extract values that do not exist in the source object and then we can post process this list to make it useful. Compare-Object can be useful in other ways as well, possibly using a static list of known good values and looking to see if a query or test we run pulls results that do not match an expected list or maybe that the results do match the expected results.

Related Post