PowerShell – Compare-Object: Select Results from Both Sides

filespowershell

I have read many example of comparing two objects, lists, arrays etc. What I can't seem to find or do is after comparing the objects and finding which one are equal, output some properties of BOTH objects

$sourceFiles | % { Compare-Object $_ $destFiles -IncludeEqual -ExcludeDifferent -Property Name}

This provides the expected result (i.e.):

Name                                                SideIndicator                                                                              
----                                                -------------    
log4net.dll                                         ==                                                                                         
Ninject.dll                                         ==                                                                                         
Ninject.Extensions.Wcf.dll                          ==  

How can I then get back to the list and output something like this (I can only do it with the first list using $_ but I don't know a way to get the destination list property:

Name                                                Path1                            Path2                                                                              
----                                                -------------                    ---------------   
log4net.dll                                         C:\test\                         \\server\test                                                                                        
Ninject.dll                                         C:\test\                         \\server\test                                                                                  
Ninject.Extensions.Wcf.dll                          C:\test\                         \\server\test

I have something like this:

$source | ForEach-Object {
   $c = Compare-Object $_.Name $dest.Name -IncludeEqual -ExcludeDifferent
   if ($c.SideIndicator.ToString() -eq "=="){
     $_ | Select-Object Name, DirectoryName
   }
}

but the output is only for objects on the first side of the compare ($source). How can I relate this output to the second list ($dest)?

Best Answer

You'll have to build a [PSCustomObject] using the Name to select the directory from both $sourceFiles and $destFiles.

It's not neccessary to use a ForEach on $sourceFiles, compare the variables directly.

$SourceFiles = Get-ChildItem 'C:\bat\' -File
$destFiles   = Get-ChildItem 'K:\Bat\' -File
Compare-Object $sourceFiles $destFiles -IncludeEqual -ExcludeDifferent -Property Name|
  ForEach-Object {
    [PSCustomObject]@{
      Name  = $_.Name
      Path1 = ($SourceFiles | Where-Object Name -eq $_.Name).Directory
      Path2 = ($destFiles   | Where-Object Name -eq $_.Name).Directory
    }
  }

Sample output:

Name              Path1  Path2
----              -----  -----
Arp-Scan.cmd      C:\bat K:\Bat
Arp-Scan.Log      C:\bat K:\Bat
BatchLib.cmd      C:\bat K:\Bat
BatchLib.INC      C:\bat K:\Bat

If you know where $sourceFiles/$destFiles stem from and they aren't build recursively Path1/Path2 are static, so the above script is IMO overkill.

Otherwise you should elaborate on the origin of $sourceFiles/$destFiles.