2

I'm trying to create a sorting function to sort my objects into three different lists. Each object contains the names of servers (among other things), under the "Name" column. I'm trying to create three lists. One that contains server names that appear on both objects, one that contains server names that only appear on the txtFile object, and one that contains server names that only appear on the csvFile object. Here is what I have so far:

If ($txtFile.Name -contains $csvFile.Name) {
    $onBothLists += $csvFile.Name
}
ElseIf ($txtFile.Name -notcontains $csvFile.Name) {
   $onlyOnTxtFile += $txtFile.Name
}
ElseIf ($csvFile.Name -notcontains $txtFile.Name) {
   $onlyOnCsvFile += $csvFile.Name
}

My issue is that when I run this, $onBothLists and $onlyOnTxtFile populate, while $onlyOnCsvFile does not. However, when I run a Compare-Object for them, it outputs three lists exactly how I expect it to. Is my logic wrong here?

JK72
  • 149
  • 1
  • 8

2 Answers2

2

You can loop over the lists yourself, but Compare-Object already does all the iterating and comparison you need. You just have to filter the results afterward. This is made easy by Group-Object.

Compare-Object returns a list of objects each containing 2 properties: the original object (.InputObject) and an indicator of which list the resulting object was found in (.SideIndicator), which shows == for objects in both, or rockets for a direction <= and =>.

By grouping on the side indicator and giving the group results as a [hashtable] we can easily index into that table by side indicator to get the results desired:

$list1 = echo serverA serverB serverC serverD serverE
$list2 = echo serverD serverE serverF serverG serverH

$grouped = Compare-Object -ReferenceObject $list1 -DifferenceObject $list2 -IncludeEqual | 
    Group-Object -Property SideIndicator -AsHashTable -AsString


# both
$grouped['=='].InputObject

# in list1
$grouped['<='].InputObject

# in list2
$grouped['=>'].InputObject

For just the ones that are the same, you can do this:

Compare-Object -ReferenceObject $list1 -DifferenceObject $list2 -IncludeEqual -ExcludeDifferent
briantist
  • 45,546
  • 6
  • 82
  • 127
  • Thanks for the response. My biggest issue with using "Compare-Object" is that I still need to use all columns within each file when done. So once the compare is done, I still need to be able to say "If ($grouped.sideIndicator -eq "==") { $finalName += $csvFile.Name, $finalOS += $csvFile.OS, $finalTarget += $csvFile.'Target Destination'}. I can't use these fields anymore if I use Compare-Object – JK72 Dec 21 '18 at 16:50
2

To build on my answer to your previous question:

## Q:\Test\2018\12\21\SO_53886784.ps1

$csvFile = Import-Csv .\sample.csv
$txtFile = Import-csv .\sample.txt -Header Name

$newCsv = Compare-Object -Ref $csvFile -Dif $txtFile -Property Name -IncludeEqual

$onBothLists   = $newCsv | Where-Object SideIndicator -eq '==' | Select-Object -Expand Name
$onlyOnTxtFile = $newCsv | Where-Object SideIndicator -eq '=>' | Select-Object -Expand Name
$onlyOnCsvFile = $newCsv | Where-Object SideIndicator -eq '<=' | Select-Object -Expand Name

Sample output:

> $onBothLists
wddg9028
htew804

> $onlyOnTxtFile
test1234

> $onlyOnCsvFile
other321