Como chegar Select-Object para retornar um tipo de matéria (por exemplo String) em vez de PSCustomObject?

StackOverflow https://stackoverflow.com/questions/618749

  •  03-07-2019
  •  | 
  •  

Pergunta

O código a seguir dá-me uma série de PSCustomObjects, como posso obtê-lo para retornar uma matriz de Cordas?

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

(Como uma questão secundária, que é a parte PSIsContainer para? Copiei que a partir de um exemplo on-line)

Post-Accept Edit: Duas grandes respostas, gostaria de poder marcar os dois. Concederam a resposta original.

Foi útil?

Solução

Você só precisa escolher o imóvel que você quer a partir dos objetos. FullName neste caso.

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

Editar: Explicação para Mark, que pergunta: "O que o foreach fazer O que é que enumerar de novo?"

A explicação de Sung Meister é muito bom, mas vou acrescentar um passo a passo aqui, pois poderia ser útil.

O conceito chave é o pipeline. Imagine uma série de bolas de pingue-pongue de rolamento para baixo um tubo estreito após o outro. Estes são os objetos no pipeline. Cada etapa do gasoduto - os segmentos de código separadas por barra vertical (|) caracteres - tem um tubo que entra nele e tubo de sair dela. A saída de um estágio está ligado à entrada da fase seguinte. Cada estágio leva os objetos que eles chegam, faz as coisas para eles, e os envia de volta para o gasoduto de saída ou envia, objetos novos de substituição.

Get-ChildItem $directory -Recurse

Get-ChildItem caminha pelo sistema de arquivos a criação de objetos FileSystemInfo que representam cada arquivo e diretório que encontra, e coloca-los na tubulação.

Select-Object FullName

Select-Object leva cada objeto FileSystemInfo como chega, pega a propriedade FullName a partir dele (que é um caminho, neste caso), coloca que a propriedade em um objeto personalizado nova marca que criou, e coloca esse objeto personalizado para fora pipeline.

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

Este é um filtro. É preciso cada objeto, examina-lo e envia-lo de volta ou devoluções-lo dependendo de alguma condição. Seu código aqui tem um bug, por sinal. Os objetos personalizados que chegam aqui não têm uma propriedade PSIsContainer. Esta fase na verdade não faz nada. código de Sung Meister é melhor.

foreach {$_.FullName}

Foreach, cujo nome longo é ForEach-Object, agarra cada objeto que ele chega, e aqui, pega a propriedade FullName, uma string, a partir dele. Agora, aqui é a parte sutil: Qualquer valor que não é consumida, isto é, não é capturado por uma variável ou suprimida de alguma forma, é colocado na tubulação de saída. Como uma experiência, tentar substituir essa fase com este:

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

Na verdade experimentá-lo e examinar a saída. Há quatro valores em que bloco de código. Nenhum deles são consumidos. Observe que todos eles aparecem na saída. Agora tente o seguinte:

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

Observe que um dos valores está sendo capturado por uma variável. Ela não aparece na calha de saída.

Outras dicas

Para obter a seqüência para o nome do arquivo que você pode usar

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

O parâmetro -ExpandProperty permite-lhe voltar um objeto com base no tipo da propriedade especificada.

Mais testes mostra que isso não funcionou com V1, mas essa funcionalidade é fixo a partir do V2 CTP3.

Para Pergunta # 1

Eu removi "select-object" parte - é redundante e mudou-se "onde" filtro antes "foreach" ao contrário de resposta de dangph - Filtro, logo que possível, para que você está lidando com apenas um subconjunto de o que você tem que lidar com a próxima linha de tubo.

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

Esse trecho de código essencialmente lê

  • Obter todos os arquivos de caminho completo de todos os arquivos de forma recursiva (Get-ChildItem $ diretório -Recurse)
  • Filtro para fora diretórios (Where-Object {! $ _. PSIsContainer})
  • retornar apenas nome completo do arquivo (foreach {$ _. FullName})
  • Salvar todos os nomes de arquivos em $ arquivos

Note que para a foreach {$ _. FullName} , em PowerShell, última declaração em um bloco de script ({...}) é retornado, neste caso $ _. FullName do tipo string

Se você realmente precisa para obter um objeto cru, você não precisa fazer nada depois de se livrar de "select-objeto". Se você fosse usar Select-Object, mas querem acesso a objetos cru, use "PsBase", que é uma questão totalmente diferente (tópico) - Consulte " o que há com PSBASE, pSEXTENDED, pSADAPTED e PSObject? " para obter mais informações sobre o assunto

Para Pergunta nº 2

E também filtrar por $ _ PSIsContainer significa que você está excluindo um recipiente objetos de nível -!. Em seu caso, você está fazendo Get-ChildItem em FileSystem provedor (você pode ver provedores PowerShell através Get-PsProvider), de modo que o recipiente é um DirectoryInfo (pasta)

PSIsContainer significa coisas diferentes em diferentes provedores PowerShell; eg) Por Registo provedor, PSIsContainer é do tipo Microsoft.Win32.RegistryKey Tente isto:

>pushd HKLM:\SOFTWARE
>ls | gm

[UPDATE] a seguinte pergunta: O que o foreach fazer? O que é que enumerar de novo? Para esclarecer, "foreach" é um apelido para "Foreach-Object" Você pode descobrir através,

get-help foreach

- ou -

get-alias foreach

Agora, na minha resposta, "foreach" é enumerando cada instância objeto do tipo FileInfo retornou de tubulação anterior (que foi filtrada diretórios). FileInfo tem uma propriedade chamada FullName e é isso que "foreach" é enumerar mais.
E você faz referência objeto passado através do gasoduto através de uma variável gasoduto especial chamado "$ _" que é do tipo FileInfo no contexto bloco de script de "foreach".

Para V1, adicione o seguinte filtro para o seu perfil:

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

Em seguida, você pode fazer isso:

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

BTW, se você estiver usando o PowerShell Community Extensions você já tem isso.

No que diz respeito a capacidade de usar Select-Object -Expand em V2, é um truque bonito, mas não é óbvio e realmente não é o que Select-Object nem -Expand foi destinado. -Expand é tudo sobre achatamento como SelectMany do LINQ e Select-Object é sobre projeção de várias propriedades em um objeto personalizado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top