2010-06-29 2 views
1

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

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 ниже корневого каталога, отфильтровывает не-каталоги, идет вверх от одного до промежуточных каталогов, затем отфильтровывает любой каталог, который не является ребенок корневого каталога.

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

Однако если изменить последний пункт, где следующим образом:

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

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

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

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

+2

Я бы, наверное, написать, что, как 'GCI | ? {$ _. psiscontainer -and (test-path $ _ \ foo)} '... – Joey

+0

@ Йоханнес Россель хе-хе это гораздо более краткий; Благодарю. – tenpn

ответ

3

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

Смотрите, если это делает трюк:

$rootDir = gi . 
gci . -r *Foo* | ?{$_.PSIsContainer -and $_.Name -eq 'Tools' -and ` 
        $_.Parent.Name -eq $rootDir.Name} 
+0

Спасибо. Я задавался вопросом, является ли -eq ссылочным сравнителем или значением, и если есть какой-то способ сделать его последним. Но из того, что вы говорите, это просто чисто класс .Net, который я использую. В будущем мне нужно будет проверить MSDN, чтобы убедиться, что класс, который я использую, поддерживает равенство (в данном случае System.IO.DirectoryInfo). – tenpn

2

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

-Oisin