comparing Item sets in PowerShell
Feb. 17th, 2024 08:38 am![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Once I needed to write a not-that-complex script, which should copy "new" files from source folder into destination one, where "new" meant that files of the same name should be absent in both dest.folder, and backup folder, into which these files were moved after processing them by other software.
In Unix/Linux&sh/bash, the tool of choice would of course be comm(1), while in Windows&PowerShell, Compare-Object is most often used. So I made these functions,
function union { Compare-object @( $args[0] ) @( $args[1] ) -PassThru -IncludeEqual }
function difference { Compare-Object @( $args[0] ) @( $args[1] ) |
where {$_.sideIndicator -eq '<='} |
select -ExpandProperty InputObject }
, and shortly, after some experiments, I discovered that PS Item Objects, being kind of maps of named properties to their values, are not comparable by equality ($O1 -eq $O2) or by inclusion of an object into a list ($L -contains $O).
you may check that by yourself in some non-empty folder:
$a=(Get-ChildItem -File)
$b=(Get-ChildItem -File) # should be the same list, right ? wrong !
$a # their printout would look the same
$b # but this only confuses you more
$a[0] -eq $b[0] # False
$a -contains $b[0] # False
function filelist { Get-ChildItem -Path $args[0] -File -Filter $args[1] |
select -ExpandProperty Name }
file lists formed in this way finally were able to be properly unioned and differenced with the above functions.
In Unix/Linux&sh/bash, the tool of choice would of course be comm(1), while in Windows&PowerShell, Compare-Object is most often used. So I made these functions,
function union { Compare-object @( $args[0] ) @( $args[1] ) -PassThru -IncludeEqual }
function difference { Compare-Object @( $args[0] ) @( $args[1] ) |
where {$_.sideIndicator -eq '<='} |
select -ExpandProperty InputObject }
, and shortly, after some experiments, I discovered that PS Item Objects, being kind of maps of named properties to their values, are not comparable by equality ($O1 -eq $O2) or by inclusion of an object into a list ($L -contains $O).
you may check that by yourself in some non-empty folder:
$a=(Get-ChildItem -File)
$b=(Get-ChildItem -File) # should be the same list, right ? wrong !
$a # their printout would look the same
$b # but this only confuses you more
$a[0] -eq $b[0] # False
$a -contains $b[0] # False
you may select only a single property from these Item lists, like:
$a=(Get-ChildItem -File | Select-Object -Property Name )
$b=(Get-ChildItem -File | Select-Object -Property Name )
but this would not improve your results as well.
What is worse, for Item lists taken from the same folder, Compare-Object would return properly-looking results, that is, "no difference between lists, all items are equal". But when you compare file lists taken from different folders, reviewing Compare-Object results would make you ask "What the hell?" (especially when you only select Name property from these Items).
function filelist { Get-ChildItem -Path $args[0] -File -Filter $args[1] |
select -ExpandProperty Name }
file lists formed in this way finally were able to be properly unioned and differenced with the above functions.