Сравнение родительского каталога с другим каталогом в канале where - PullRequest
1 голос
/ 29 июня 2010

Представьте, что у меня есть структура каталогов, например:

parentDir\dirA\foo\
parentDir\dirB\foo\
parentDir\dirC\
parentDir\dirD\bar\foo\
parentDir\dirE\foo\
parentDir\dirF\

Я хочу выбрать только каталоги, которые а) являются непосредственными потомками parentDir и б) имеют каталог foo в качестве непосредственного потомка.

Таким образом, категории A, B и E соответствуют требованиям, а C, D и F. - нет.

Я впервые попробовал этот скрипт powershell:

$rootDir = gi(".")
dir -include "*foo*" -recurse | ? {$_.PSIsContainer -eq $true} | % {$_.Parent} 
    | ? { $_.Parent -eq $rootDir } 

Он находит все элементы foo ниже корневого каталога, отфильтровывает не-каталоги, переходит один в промежуточные каталоги, затем отфильтровывает любой каталог, который не является дочерним для корневого каталога.

Возвращает пустой список.

Однако, если я изменю последнее предложение where следующим образом:

? { $_.Parent.FullName -eq $rootDir.Fullname }

Это работает, и я получаю правильный вывод каталогов.

Итак, мой вопрос: почему не работает прямое сравнение между объектами каталога? Это может показаться мелочью, но это подразумевает, что в моем понимании объектов powershell есть некоторая дыра.

(Кроме того, не стесняйтесь критиковать мой стиль кодирования powershell в сценариях или указывать более быстрые / более правильные способы сделать это)

Ответы [ 2 ]

3 голосов
/ 29 июня 2010

При сравнении объектов .NET, существует ряд факторов. Во-первых, сравнение может быть простым сравнением равенства ссылок, то есть ссылается ли эта переменная на тот же объект, на который ссылается другая переменная. Во многих случаях (большинство ссылочных типов) это поведение по умолчанию для равенства. Однако существуют другие типы (типы значений), которые делают равенство на основе значения полей в объекте, например. DateTime, TimeSpan, Int32, Double и т. Д. Затем существуют объекты, которые переопределяют поведение по умолчанию, переопределяя оператор == или и / или переопределяя виртуальный метод Equals (). String - это ссылочный тип, который переопределяет их для обеспечения равенства на основе значений.

Посмотрите, поможет ли это:

$rootDir = gi .
gci . -r *Foo* | ?{$_.PSIsContainer -and $_.Name -eq 'Tools' -and `
                   $_.Parent.Name -eq $rootDir.Name}
2 голосов
/ 29 июня 2010

Два разных экземпляра класса DirectoryInfo не считаются равными, даже если они указывают на один и тот же путь.С другой стороны, две строки всегда считаются равными, если они содержат одинаковые буквы в одном и том же порядке.

-Oisin

...