Pipeline e objetos
Esta aula explora o pipeline do PowerShell, mostrando como objetos fluem entre cmdlets, como as propriedades são preservadas e como encadear comandos para processamento eficiente. Inclui exemplos práticos e exercícios para fixação.
O pipeline é um dos recursos mais poderosos do PowerShell. Diferente de shells tradicionais que passam apenas texto, o PowerShell passa objetos .NET completos entre cmdlets. Isso significa que você pode usar cmdlets como Where-Object, Select-Object e ForEach-Object para filtrar, selecionar e transformar dados sem perder a estrutura original.
Nesta aula, você aprenderá como os objetos fluem pelo pipeline, como as propriedades são preservadas e como encadear múltiplos cmdlets para criar soluções elegantes. Vamos explorar exemplos práticos que demonstram a diferença entre pipelines textuais e orientados a objetos.
Como objetos fluem
Quando você executa um comando como Get-Process | Stop-Process, o PowerShell executa o cmdlet da esquerda (Get-Process) que produz objetos do tipo System.Diagnostics.Process. Cada objeto é enviado individualmente para o próximo cmdlet (Stop-Process), que o recebe como entrada. Esse fluxo é síncrono e orientado a objetos, permitindo que o segundo cmdlet acesse diretamente propriedades e métodos do objeto.
O pipeline não espera que todos os objetos sejam gerados antes de começar a processar. Ele funciona de forma streaming: assim que um objeto está pronto, ele é passado adiante. Isso reduz o uso de memória e permite processar conjuntos de dados grandes de forma eficiente. Por exemplo, 1..1000000 | ForEach-Object { $_ * 2 } processa um milhão de números sem armazenar todos na memória ao mesmo tempo.
Propriedades preservadas
Como os objetos passam pelo pipeline intactos, todas as suas propriedades e métodos permanecem acessíveis. Você pode usar Select-Object para escolher propriedades específicas, Where-Object para filtrar baseado em valores de propriedades e Sort-Object para ordenar. Por exemplo:
Get-Process | Where-Object { $_.CPU -gt 10 } | Select-Object Name, CPU, IdNeste comando, Get-Process retorna objetos Process. O Where-Object filtra aqueles cuja propriedade CPU é maior que 10. O Select-Object então cria um novo objeto personalizado com apenas as propriedades Name, CPU e Id. Note que o objeto original não é destruído; um novo objeto é criado a partir das propriedades selecionadas.
Outra forma de trabalhar com propriedades é usando Format-Table ou Format-List para exibição, mas lembre-se de que esses cmdlets convertem objetos em texto, quebrando o pipeline de objetos. Para manter a estrutura, use Select-Object ou ForEach-Object.
Encadeando cmdlets
O pipeline permite encadear vários cmdlets, formando uma sequência de processamento. Cada cmdlet recebe objetos do anterior, processa e os envia para o próximo. Você pode combinar cmdlets de filtro, seleção, ordenação e agrupamento. Por exemplo:
Get-Service | Where-Object { $_.Status -eq 'Running' } | Sort-Object DisplayName | Select-Object Name, DisplayName, StatusIsso obtém todos os serviços, filtra apenas os em execução, ordena pelo nome de exibição e seleciona três propriedades. A ordem dos cmdlets importa: coloque filtros o mais cedo possível para reduzir o número de objetos processados.
Você também pode usar ForEach-Object para executar ações em cada objeto, como converter ou modificar dados. Por exemplo:
Get-Process | ForEach-Object { $_.Name.ToUpper() }Isso retorna uma lista de nomes de processos em maiúsculas. O pipeline é flexível: você pode até mesmo passar objetos para cmdlets que aceitam entrada por pipeline, como Stop-Process ou Remove-Item.
Exemplos
Vamos ver alguns exemplos completos que mostram o poder do pipeline orientado a objetos.
Exemplo 1: Encontrar processos que consomem mais de 100 MB de memória
Get-Process | Where-Object { $_.WorkingSet64 -gt 100MB } | Sort-Object WorkingSet64 -Descending | Select-Object Name, Id, @{Name='Memory (MB)'; Expression={[math]::Round($_.WorkingSet64 / 1MB, 2)}}Aqui usamos Where-Object para filtrar, Sort-Object para ordenar e Select-Object com uma propriedade calculada para exibir a memória em megabytes.
Exemplo 2: Parar todos os serviços que começam com 'X' e estão parados
Get-Service -Name 'X*' | Where-Object { $_.Status -eq 'Stopped' } | Stop-ServiceO pipeline envia cada serviço parado diretamente para Stop-Service, que o interrompe. Isso só é possível porque Stop-Service aceita objetos ServiceController pelo pipeline.
Exemplo 3: Criar uma lista de arquivos em um diretório com tamanho formatado
Get-ChildItem -Path C:\Temp -File | Select-Object Name, Length, LastWriteTime | ForEach-Object { $_.Length = '{0:N2} KB' -f ($_.Length / 1KB); $_ }Usamos ForEach-Object para modificar a propriedade Length para uma string formatada. Note que o objeto é modificado e depois enviado adiante (o $_ no final).
Boas práticas
- Filtre cedo: coloque
Where-Objecto mais próximo possível da origem para reduzir a quantidade de objetos processados. - Evite quebrar o pipeline: cmdlets como
Format-Tableconvertem objetos em texto; useSelect-Objectquando quiser manter objetos. - Use propriedades calculadas: em
Select-Objectvocê pode criar novas propriedades com expressões. - Teste com objetos pequenos: antes de processar grandes conjuntos, teste o pipeline com alguns objetos para garantir que funciona.
Referências
- About Pipelines - Microsoft Docs
- PowerShell 101: Pipelines - Microsoft Docs
- Where-Object - Microsoft Docs
- Select-Object - Microsoft Docs
- ForEach-Object - Microsoft Docs
- Sort-Object - Microsoft Docs
Exercícios
Escreva um comando que liste todos os processos em execução, ordenados pelo consumo de CPU (maior para menor), mostrando apenas as propriedades Name, CPU e Id.
✓ Resposta:Get-Process | Sort-Object CPU -Descending | Select-Object Name, CPU, IdUtilizando o pipeline, encontre todos os serviços que estão parados e cujo nome contenha 'SQL', e então inicie-os.
✓ Resposta:Get-Service -Name '*SQL*' | Where-Object { $_.Status -eq 'Stopped' } | Start-ServiceEscreva um comando que obtenha todos os arquivos .txt no diretório C:\Temp, selecione Name e Length (em bytes), e adicione uma propriedade calculada 'SizeKB' que mostre o tamanho em KB com duas casas decimais.
✓ Resposta:Get-ChildItem -Path C:\Temp -Filter *.txt | Select-Object Name, Length, @{Name='SizeKB'; Expression={[math]::Round($_.Length / 1KB, 2)}}Usando pipeline, crie uma lista com os 5 processos que mais consomem memória (WorkingSet64), mostrando apenas Name e WorkingSet64 (em MB), ordenados do maior para o menor.
✓ Resposta:Get-Process | Sort-Object WorkingSet64 -Descending | Select-Object -First 5 Name, @{Name='MemoryMB'; Expression={[math]::Round($_.WorkingSet64 / 1MB, 2)}}Explique a diferença entre
Get-Process | Format-Table Name, CPUeGet-Process | Select-Object Name, CPUem relação ao pipeline de objetos.✓ Resposta:Format-Tableconverte os objetos em texto formatado para exibição, quebrando o pipeline de objetos. O resultado são strings, não objetos. JáSelect-Objectcria novos objetos com as propriedades selecionadas, mantendo a estrutura orientada a objetos no pipeline. Portanto, para processamento posterior com cmdlets comoWhere-Object, useSelect-Object; para exibição final, useFormat-Table.