powershell pscustomobject

powershell - ¿Cómo hacer que Select-Object devuelva un tipo crudo(por ejemplo, String) en lugar de PSCustomObject?



(4)

Para V1, agregue el siguiente filtro a su perfil:

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

Entonces puedes hacer esto:

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

Por cierto, si está utilizando las extensiones de comunidad de PowerShell , ya tiene esto.

En cuanto a la capacidad de usar Select-Object -Expand en V2, es un truco lindo pero no obvio, y realmente no es para lo que Select-Object ni -Expand fue diseñado. -Expand se trata de aplanar como LINK SelectMany y Select-Object se trata de la proyección de múltiples propiedades en un objeto personalizado.

El siguiente código me proporciona una matriz de PSCustomObjects, ¿cómo puedo obtener que devuelva una matriz de cadenas?

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

(Como una pregunta secundaria, ¿para qué sirve la parte psiscontainer? Copié eso de un ejemplo en línea)

Edición post-aceptación: Dos excelentes respuestas, ojalá pudiera marcarlas a ambas. Haber otorgado la respuesta original.


Para obtener la cadena para el nombre del archivo, puede usar

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

El parámetro -ExpandProperty le permite recuperar un objeto según el tipo de propiedad especificada.

Pruebas adicionales muestran que esto no funcionó con V1, pero que la funcionalidad se corrigió a partir del V2 CTP3.


Solo necesita elegir la propiedad que desea de los objetos. FullName en este caso.

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

Editar: Explicación para Mark, que pregunta: "¿Qué hace el foreach? ¿Qué es eso que enumera?"

La explicación de Sung Meister es muy buena, pero agregaré un tutorial aquí porque podría ser útil.

El concepto clave es la tubería. Imagina una serie de bolas de ping-pong rodando por un tubo estrecho una después de la otra. Estos son los objetos en la tubería. Cada etapa de la tubería - los segmentos de código separados por caracteres de tubería (|) - tiene una tubería que entra y sale de la tubería. La salida de una etapa está conectada a la entrada de la siguiente etapa. Cada etapa toma los objetos a medida que llegan, les hace cosas y los envía de regreso a la tubería de salida o envía nuevos objetos de reemplazo.

Get-ChildItem $directory -Recurse

Get-ChildItem recorre el sistema de archivos creando objetos FileSystemInfo que representan cada archivo y directorio que encuentra, y los coloca en la tubería.

Select-Object FullName

Select-Object toma cada objeto FileSystemInfo cuando llega, toma la propiedad FullName de él (que es una ruta en este caso), coloca esa propiedad en un nuevo objeto personalizado que ha creado y coloca ese objeto personalizado en la tubería.

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

Este es un filtro Toma cada objeto, lo examina y lo envía de vuelta o lo descarta dependiendo de alguna condición. Su código aquí tiene un error, por cierto. Los objetos personalizados que llegan aquí no tienen una propiedad psiscontainer. Esta etapa en realidad no hace nada. El código de Sung Meister es mejor.

foreach {$_.FullName}

Foreach, cuyo nombre largo es ForEach-Object, toma cada objeto cuando llega, y aquí, toma la propiedad FullName, una cadena, de él. Ahora, aquí está la parte sutil: cualquier valor que no se consuma, es decir, no sea capturado por una variable o suprimido de alguna manera, se ponga en la línea de salida. Como experimento, intente reemplazar esa etapa con esto:

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

En realidad, pruébelo y examina la salida. Hay cuatro valores en ese bloque de código. Ninguno de ellos se consume. Tenga en cuenta que todos aparecen en la salida. Ahora prueba esto:

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

Tenga en cuenta que uno de los valores está siendo capturado por una variable. No aparece en la canalización de salida.


Para la pregunta n. ° 1

He eliminado la parte de "seleccionar objeto" - es redundante y moví el filtro "donde" antes de "foreach" a diferencia de la respuesta de dangph - Filtre tan pronto como sea posible para que se ocupe solo de un subconjunto de lo que tiene que tratar en la próxima línea de tubería

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

Ese fragmento de código esencialmente dice

  • Obtenga todos los archivos con la ruta completa de todos los archivos recursivamente (Get-ChildItem $ directory -Recurse)
  • Filtrar directorios (Where-Object {! $ _. PsIsContainer})
  • Devuelve solo el nombre completo del archivo (foreach {$ _. FullName})
  • Guarde todos los nombres de archivos en $ archivos

Tenga en cuenta que para foreach {$ _. FullName} , en powershell, se devuelve la última instrucción en un bloque de script ({...}), en este caso $ _. FullName de tipo cadena

Si realmente necesita obtener un objeto sin procesar, no necesita hacer nada después de deshacerse del "objeto de selección". Si tuviera que usar Select-Object pero desea acceder a un objeto sin procesar, use "PsBase", que es una pregunta totalmente diferente (tema). Consulte " ¿Qué pasa con PSBASE, PSEXTENDED, PSADAPTED y PSOBJECT? " Para obtener más información sobre ese sujeto

Para la pregunta n. ° 2

Y también al filtrar por ! $ _. PsIsContainer significa que está excluyendo un contenedor de objetos a nivel: en su caso, usted está haciendo Get-ChildItem en un proveedor de FileSystem (puede ver proveedores de PowerShell a través de Get-PsProvider), por lo que el contenedor es DirectoryInfo (carpeta)

PsIsContainer significa cosas diferentes bajo diferentes proveedores de PowerShell; eg) Para el proveedor de registro , PsIsContainer es de tipo Microsoft.Win32.RegistryKey Pruebe esto:

>pushd HKLM:/SOFTWARE >ls | gm

[ACTUALIZAR] a la siguiente pregunta: ¿Qué hace el foreach? ¿Qué es eso que enumera? Para aclarar, "foreach" es un alias para "Foreach-Object" que puedes encontrar a través de,

get-help foreach

- o -

get-alias foreach

Ahora, en mi respuesta, "foreach" enumera cada instancia de objeto de tipo FileInfo devuelto desde el canal anterior (que tiene directorios filtrados). FileInfo tiene una propiedad llamada FullName y eso es sobre lo que "foreach" está enumerando.
Y usted hace referencia al objeto pasado a través de una tubería a través de una variable especial llamada "$ _" que es de tipo FileInfo dentro del contexto del bloque de script de "foreach".