Pipeline e objetos
Esta aula explica como o pipeline do PowerShell funciona, destacando que objetos, e não texto, fluem entre cmdlets. Você aprenderá a preservar propriedades, encadear comandos com Where-Object, Select-Object e ForEach-Object, e verá exemplos práticos que demonstram a eficiência dessa abordagem.
O pipeline é um dos recursos mais poderosos do PowerShell. Diferente de shells tradicionais que passam apenas texto entre comandos, o PowerShell transmite objetos .NET completos. Isso significa que cada cmdlet pode acessar diretamente propriedades e métodos dos objetos recebidos, sem necessidade de parsing textual. Nesta aula, exploraremos como os objetos fluem pelo pipeline, como as propriedades são preservadas, como encadear cmdlets de forma eficiente e exemplos práticos que ilustram esses conceitos.
Entender o pipeline é essencial para escrever scripts concisos e performáticos. Ao dominar o fluxo de objetos, você poderá combinar cmdlets em sequências poderosas, filtrar dados com precisão e transformar informações sem sair do contexto do PowerShell.
Como objetos fluem
Quando você conecta dois cmdlets com o operador pipe (|), o cmdlet da esquerda produz objetos que são enviados um a um para o cmdlet da direita. O cmdlet da direita processa cada objeto assim que ele chega, sem esperar que todos sejam gerados. Esse fluxo é chamado de processamento em streaming e permite trabalhar com grandes volumes de dados sem consumir muita memória.
Por exemplo, ao executar Get-Process | Stop-Process, o cmdlet Get-Process começa a emitir objetos de processo. Cada objeto é imediatamente recebido por Stop-Process, que encerra o processo correspondente. Se houver muitos processos, o pipeline os processa em tempo real, sem armazenar todos na memória.
Get-Service | Where-Object { $_.Status -eq 'Running' }Nesse exemplo, Get-Service produz objetos de serviço, e Where-Object filtra apenas aqueles cuja propriedade Status seja igual a 'Running'. O objeto atual é referenciado por $_ dentro do bloco de script.
Propriedades preservadas
Como o pipeline transmite objetos, todas as propriedades e métodos do objeto original permanecem disponíveis ao longo da cadeia. Isso elimina a necessidade de extrair texto e fazer expressões regulares para obter informações. Por exemplo, um processo tem propriedades como Name, Id, CPU, WorkingSet, etc. Você pode acessá-las diretamente em qualquer cmdlet que receba o objeto.
O cmdlet Select-Object permite escolher quais propriedades você deseja manter no pipeline, criando um novo objeto com um subconjunto de propriedades. Já Format-List ou Format-Table são usados apenas para exibição, mas não alteram o objeto subjacente.
Get-Process -Name notepad | Select-Object Name, CPU, WorkingSetIsso retorna objetos com apenas as propriedades Name, CPU e WorkingSet. Se você quiser adicionar propriedades calculadas, pode usar uma hashtable:
Get-Process | Select-Object Name, @{Name='MemMB'; Expression={[math]::Round($_.WorkingSet/1MB,2)}}Encadeando cmdlets
O verdadeiro poder do pipeline está em encadear múltiplos cmdlets para realizar tarefas complexas em uma única linha. Os cmdlets mais comuns para encadeamento são Where-Object (filtro), Select-Object (seleção de propriedades), ForEach-Object (processamento personalizado) e Sort-Object (ordenação).
Por exemplo, para listar os 5 processos que mais consomem memória, formatando o resultado:
Get-Process | Sort-Object WorkingSet -Descending | Select-Object -First 5 Name, WorkingSet | Format-Table -AutoSizeOutro exemplo: parar todos os serviços que estão em execução e cujo nome começa com 'A':
Get-Service | Where-Object { $_.Status -eq 'Running' -and $_.Name -like 'A*' } | Stop-ServiceNote que Stop-Service aceita objetos de serviço diretamente, então não é necessário extrair o nome.
Exemplos
Vamos consolidar com exemplos práticos que ilustram o uso do pipeline com objetos.
Exemplo 1: Obter informações de arquivos em uma pasta, filtrar por tamanho e exibir nome e tamanho em MB.
Get-ChildItem C:\Temp\*.log | Where-Object { $_.Length -gt 1MB } | Select-Object Name, @{Name='SizeMB'; Expression={[math]::Round($_.Length/1MB,2)}}Exemplo 2: Encerrar todos os processos do Chrome que estão rodando há mais de 1 hora.
Get-Process -Name chrome | Where-Object { $_.StartTime -lt (Get-Date).AddHours(-1) } | Stop-Process -ForceExemplo 3: Exportar serviços em execução para um arquivo CSV com apenas nome e status.
Get-Service | Where-Object { $_.Status -eq 'Running' } | Select-Object Name, Status | Export-Csv -Path services.csv -NoTypeInformationEsses exemplos mostram como o pipeline permite compor operações de forma clara e eficiente, mantendo a integridade dos objetos.
Boas práticas
- Prefira usar
Where-Objectantes deSelect-ObjectouForEach-Objectpara reduzir o número de objetos processados. - Evite quebrar o pipeline com parênteses desnecessários; use subexpressões apenas quando precisar de um resultado intermediário.
- Utilize propriedades calculadas com
Select-Objectpara transformar dados sem recorrer a loops explícitos. - Teste pipelines com poucos objetos antes de aplicá-los a grandes conjuntos.
Referências
- Understanding the PowerShell Pipeline - Microsoft Docs
- about_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 que estão consumindo mais de 100 MB de memória (WorkingSet > 100MB), exibindo apenas o nome e o WorkingSet em MB.
✓ Resposta:Get-Process | Where-Object { $_.WorkingSet -gt 100MB } | Select-Object Name, @{Name='WorkingSetMB'; Expression={[math]::Round($_.WorkingSet/1MB,2)}}Obtenha todos os serviços que estão parados e cujo nome começa com 'W', e então inicie-os.
✓ Resposta:Get-Service | Where-Object { $_.Status -eq 'Stopped' -and $_.Name -like 'W*' } | Start-ServiceListe os 3 maiores arquivos (em tamanho) na pasta C:\Windows\System32, exibindo nome, tamanho em KB e data de criação.
✓ Resposta:Get-ChildItem C:\Windows\System32 | Sort-Object Length -Descending | Select-Object -First 3 Name, @{Name='SizeKB'; Expression={[math]::Round($_.Length/1KB,2)}}, CreationTimeCrie um comando que calcule a média de CPU (propriedade CPU) de todos os processos do navegador Chrome (nome 'chrome') e exiba o resultado.
✓ Resposta:Get-Process -Name chrome | Measure-Object -Average CPU | Select-Object AverageExporte para um arquivo CSV chamado 'eventos.csv' os 10 eventos mais recentes do log de sistema (System) que tenham nível de erro (EntryType -eq 'Error'), exibindo TimeGenerated, Message e EntryType.
✓ Resposta:Get-EventLog -LogName System -EntryType Error | Sort-Object TimeGenerated -Descending | Select-Object -First 10 TimeGenerated, Message, EntryType | Export-Csv -Path eventos.csv -NoTypeInformation