2010-06-29 10 views
1

Imaginez-je une structure de répertoire parent d'un répertoire comme ceci:comparaison contre un autre répertoire dans un où tuyau

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

Je veux sélectionner uniquement les répertoires qui a) sont des enfants immédiats de parentdir, et b) ont un répertoire foo en tant qu'enfant immédiat.

Ainsi, les répertoires A, B et E sont admissibles, tandis que C, D et F ne le sont pas.

j'ai essayé ce script Powershell:

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

Il trouve tous les éléments de foo en dessous du répertoire racine, filtre les non-répertoires, monte un aux répertoires intermédiaires, puis des filtres sur un répertoire qui n'est pas un enfant de la racine

Ceci retourne une liste vide.

Cependant, si je change la dernière clause where comme suit:

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

Il fonctionne, et je reçois la sortie des répertoires corrects. Donc, ma question est la suivante: pourquoi une comparaison directe entre les objets répertoire ne fonctionne-t-elle pas? Cela peut sembler une petite chose mais cela implique qu'il y a un trou dans ma compréhension des objets PowerShell.

(Aussi, ne hésitez pas à critiquer mon powershell style de codage dans les scripts, ou indiquer des moyens plus rapides/plus correct de le faire)

+2

je serais probablement écrire que 'DCG | ? {$ _. psiscontainer -et (test-path $ _ \ foo)} '... – Joey

+0

@Johannes Rossel heh c'est beaucoup plus concis; Merci. – tenpn

Répondre

3

Lorsque l'on compare les objets .NET, il y a un certain nombre de facteurs en jeu. Tout d'abord, la comparaison peut être une simple comparaison d'égalité de référence, c'est-à-dire que cette variable fait référence exactement au même objet que l'autre référence. Dans la plupart des cas (la plupart des types de référence), il s'agit du comportement par défaut pour l'égalité. Il existe cependant d'autres types (types de valeur) qui font l'égalité en fonction de la valeur des champs dans un objet, par exemple. DateTime, TimeSpan, Int32, Double, etc. Ensuite, il existe des objets qui remplacent le comportement par défaut en remplaçant l'opérateur == ou et/ou en remplaçant la méthode virtuelle Equals(). String est un type de référence qui les remplace pour fournir une égalité "basée sur les valeurs".

Voir si cela fait l'affaire:

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

Merci. Je me demandais si -eq était un comparateur ou une valeur de référence, et s'il y avait un moyen de faire en sorte que ce soit le dernier. Mais d'après ce que vous dites, c'est uniquement pour la classe .Net que j'utilise. À l'avenir, je devrai vérifier MSDN pour voir si la classe que j'utilise supporte l'égalité (dans ce cas System.IO.DirectoryInfo). – tenpn

2

Deux différentes instances de la classe DirectoryInfo ne sont pas considérés comme égaux, même si elles pointez sur le même chemin. D'autre part, deux chaînes sont toujours considérées comme égales si elles contiennent les mêmes lettres, dans le même ordre.

-Oisin