Imagine I have a directory structure like so:
parentDir\dirA\foo\
parentDir\dirB\foo\
parentDir\dirC\
parentDir\dirD\bar\foo\
parentDir\dirE\foo\
parentDir\dirF\
I want to select only the directories that a) are immediate children of parentDir, and b) have a foo directory as an immediate child.
So dirs A, B, and E qualify, whilst C, D, and F don’t.
I first tried this powershell script:
$rootDir = gi(".")
dir -include "*foo*" -recurse | ? {$_.PSIsContainer -eq $true} | % {$_.Parent}
| ? { $_.Parent -eq $rootDir }
It finds all foo items below the root dir, filters out non-directories, goes up one to the intermediate directories, then filters out any directory which is not a child of the root dir.
This returns an empty list.
However if I change the last where clause as follows:
? { $_.Parent.FullName -eq $rootDir.Fullname }
It works, and I get the correct directories output.
So my question is, why won’t a direct compare between directory objects work? It may seem like a little thing but it implies there’s some hole in my understanding of powershell objects.
(Also, feel free to critique my powershell coding style in the scripts, or point out quicker/more correct ways of doing this)
When comparing .NET objects, there are a number of factors at play. First, the compare can be a simple reference equality comparison i.e. does this variable reference the exact same object that the other variable references. In many cases (most reference types), this is the default behavior for equality. There are other types (value types) however that do equality based the value of the fields in an object e.g. DateTime, TimeSpan, Int32, Double, etc. Then there are objects override the default behavior by overriding operator == or and/or overriding Equals() virtual method. String is a reference type that overrides these to provide “value-based” equality.
See if this does the trick: