Comment obtenir Select-Object pour retourner un type brut (par exemple String) plutôt que PSCustomObject?

le code suivant me donne un tableau de PSCustomObjects, Comment puis-je le faire retourner un tableau de chaînes?

$files = Get-ChildItem $directory -Recurse | Select-Object FullName | Where-Object {!($_.psiscontainer)}

(comme question secondaire, à quoi sert la partie psiscontainer? J'ai copié qu'à partir d'un exemple en ligne)

Post-Accepter la modification: Deux grandes réponses, souhaite que je pourrais marquer les deux d'entre eux. Ont accordé la réponse originale.

27
demandé sur Sung Kim 2009-03-06 15:49:25

4 réponses

vous avez juste besoin de choisir la propriété que vous voulez parmi les objets. FullName dans ce cas.

$files = Get-ChildItem $directory -Recurse | Select-Object FullName | Where-Object {!($_.psiscontainer)} | foreach {$_.FullName}

Edit: Explication Pour Mark, qui demande," Que fait l'étranger? Qu'est-ce que cette énumération?"

Chanté de Meister explication est très bonne, mais je vais ajouter une procédure pas à pas ici, car il pourrait vous être utile.

le concept clé est le pipeline. Imaginez une série de boules de pingpong rouler dans un tube étroit l'un après l'autre. Ce sont les objets dans le pipeline. Chaque étape du pipeline--les segments de code séparés par les caractères de la canalisation ( | )--comporte une canalisation qui y pénètre et une canalisation qui en sort. La sortie d'un stade est connecté à l'entrée de la prochaine étape. Chaque étape prend les objets au fur et à mesure qu'ils arrivent, leur fait des choses et les renvoie dans le pipeline de sortie ou envoie de nouveaux objets de remplacement.

Get-ChildItem $directory -Recurse

Get-ChildItem walks à travers le système de fichiers, créer des objets FileSystemInfo qui représentent chaque fichier et répertoire qu'il rencontre, et les mettre dans le pipeline.

Select-Object FullName

Select-Object prend chaque objet FileSystemInfo à mesure qu'il arrive, saisit la propriété FullName de celui-ci (qui est un chemin dans ce cas), place cette propriété dans un nouvel objet personnalisé qu'il a créé, et met cet objet personnalisé dans le pipeline.

Where-Object {!($_.psiscontainer)}

C'est un filtre. Il prend chaque objet, l'examine, et le renvoie ou le jette selon une condition. Votre code a un bug, au fait. Les objets personnalisés qui arrivent ici n'ont pas de propriété psiscontainer. Cette étape n'a pas réellement faire quelque chose. Le code de Sung Meister est meilleur.

foreach {$_.FullName}

Foreach, dont le nom long est ForEach-Object, saisit chaque objet au fur et à mesure qu'il arrive, et ici, saisit la propriété FullName, une chaîne, à partir de celle-ci. Maintenant, voici la partie subtile: Toute valeur qui n'est pas consommée, qui est, n'est pas capturé par une variable ou supprimé, d'une certaine façon, est mis dans la sortie du pipeline. À titre expérimental, essayez de remplacer cette étape par ce qui suit:

foreach {'hello'; $_.FullName; 1; 2; 3}

en fait essayer et examiner la sortie. Il y a quatre valeurs dans ce bloc de code. Aucun d'entre eux sont consommés. Notez qu'ils apparaissent tous dans la sortie. Maintenant, essayez ceci:

foreach {'hello'; $_.FullName; $ x = 1; 2; 3}

remarquez qu'une des valeurs est saisie par une variable. Il n'apparaît pas dans le pipeline de sortie.

32
répondu dan-gph 2009-03-07 00:59:02

Pour obtenir la chaîne de caractères pour le nom de fichier vous pouvez utiliser

$files = Get-ChildItem $directory -Recurse | Where-Object {!($_.psiscontainer)} | Select-Object -ExpandProperty FullName

le paramètre -ExpandProperty vous permet de récupérer un objet basé sur le type de propriété spécifié.

D'autres tests montrent que cela n'a pas fonctionné avec V1, mais que la fonctionnalité est fixe dès le V2 CTP3.

17
répondu Steven Murawski 2018-06-29 07:32:14

Pour La Question #1

j'ai supprimé la partie" select-object "- c'est redondant et déplacé" où "filtre avant" foreach "contrairement à réponse de dangph - filtre dès que possible de sorte que vous avez affaire à un sous-ensemble de ce que vous avez à traiter dans la ligne de conduite suivante.

$files = Get-ChildItem $directory -Recurse | Where-Object {!$_.PsIsContainer} | foreach {$_.FullName}

cet extrait de code se lit essentiellement

  • Obtenir tous les fichiers complet chemin de tous les fichiers récursivement (Get-ChildItem $directory-Recurse)
  • filtrer les répertoires (où-objet {!$ _ .PsIsContainer})
  • retourner le nom complet du fichier seulement (foreach {$_.FullName})
  • Enregistrer tous les noms de fichier dans $files

noter que pour pour chaque.FullName} , dans powershell, la dernière instruction dans un bloc de script ({...}) est renvoyée, dans ce cas,$_.Nom complet du type string

si vous avez vraiment besoin d'obtenir un objet brut, vous n'avez pas besoin de faire quoi que ce soit après vous être débarrassé de"select-object". Si vous deviez utiliser Select-Object mais que vous voulez accéder à l'objet brut, utilisez "PsBase", qui est une question totalement différente ( topic) - se référer à" Quoi de neuf avec PSBASE, PSEXTENTED, PSADAPTED, et PSOBJECT? " pour plus d'informations sur le sujet

Pour La Question #2

"

et aussi filtrage par !$ _ .PsIsContainer signifie que vous excluez un niveau de conteneur objets - dans votre cas, vous faites Get-ChildItem sur un FileSystem fournisseur (vous pouvez voir les fournisseurs PowerShell par Get-PsProvider), donc le conteneur est un DirectoryInfo (dossier)

PsIsContainer signifie différentes choses sous différents Fournisseurs de PowerShell; par exemple) pour Registre fournisseur, PsIsContainer est de type Microsoft.Win32.RegistryKey Essayez ceci:

>pushd HKLM:\SOFTWARE
>ls | gm

[mise à JOUR] à la question suivante: Quel est le foreach? Qu'est-ce que cette énumération? Pour clarifier, "foreach" est un alias pour " Foreach-Object" Vous pouvez trouver à travers,

get-help foreach

-- ou --

get-alias foreach

maintenant dans ma réponse, " foreach "est l'énumération de chaque instance d'objet de type FileInfo retourné de la pipe précédente (qui a filtré les annuaires). FileInfo a une propriété appelée FullName et c'est ce que "foreach" est en train d'énumérer.

Et vous référence objet passé par pipeline à travers une variable de pipeline spécial appelé "$ _ " qui est de type FileInfo dans le bloc de script contexte de "foreach".

8
répondu Sung Kim 2017-05-23 12:17:50

pour V1, ajouter le filtre suivant à votre profil:

filter Get-PropertyValue([string]$name) { $_.$name }

alors vous pouvez faire ceci:

gci . -r | ?{!$_.psiscontainer} | Get-PropertyName fullname

BTW, si vous utilisez les PowerShell Community Extensions vous avez déjà ceci.

en ce qui concerne la capacité D'utiliser Select-Object-Expand dans V2, c'est un truc mignon mais pas évident et n'est pas vraiment ce que Select-Object nor-Expand était censé faire. - L'expansion est une question d'aplatissement comme SelectMany et Select-Object de LINQ, il s'agit de projeter de multiples propriétés sur un objet personnalisé.

4
répondu Keith Hill 2009-03-22 06:50:51