powershellpropertiescompareobject

Compare-Object (powershell) : return a property but don't compare with it


I am using Compare-Object to compare 2 bidimensional arrays issued by Get-ChildItem.

I am asking it to compare using the Name property using -Property 'Name'

This returns a table with the Name property and SideIndicator.

The problem is that I would like to know not only the name of the file, but also its complete path; if I ask Compare-Object ... -Property @{ Expression = {"$($_.Directory)\$($_.Name)"} }, it compares using the path, which is not what I want either (this tool I'm coding will be to sync up 2 folders, so obviously the paths are different, hence getting all the files scored as different).

Please let me know if you need more details !


Solution

  • If you use Compare-Object with -Property in order to compare the two input collections by one or more specific property values only, by default the output objects contain those properties only, alongside the .SideIndicator property that signals which of the two input collections a given difference came from:

    # Sample input collections.
    $c1 = @(Get-Date) # a single-element array containing a [datetime] instance
    $c2 = @()         # empty array
    
    # Due to -Property Day, the output object contains only the .Day property value, 
    # not the whole date.
    # -> [pscustomobject] @{ Day = 21; SideIndicator = '<=' }
    Compare-Object -Property Day -ReferenceObject $c1 -DifferenceObject $c2
    

    To instead pass the whole original objects through, use the -PassThru switch.

    That is, instead of emitting [pscustomobject] instances with a .SideIndicator property, -PassThru causes the input objects themselves to be emitted.
    However, so that you can still determine which side (input collection) a given object came from, the original objects are decorated with a .SideIndicator property, using PowerShell's ETS (Extended Type System).

    $c1 = @(Get-Date)
    $c2 = @()
    
    # Due to adding -PassThru, the output is now the whole date.
    $differingDates = 
      Compare-Object -Property Day -PassThru $c1 $c2
    
    # The original [datetime] instance was returned, decorated with a
    # .SideIndicator property.
    $differingDates.SideIndicator # -> '<='
    

    Caveats:


    [1] In PowerShell (Core) 7.2+, ConvertTo-Json now automatically and invariably ignores ETS properties of [string] and [datetime] instances, specifically. See GitHub issue #5797 for the original discussion that led to this change.