No PowerShell, a manipulação de coleções de dados é uma tarefa frequente. Os cmdlets Sort-Object e Group-Object são ferramentas essenciais para organizar e sumarizar informações, respectivamente. Com eles, você pode ordenar resultados de comandos por propriedades específicas, agrupar objetos com base em valores comuns e até contar quantos itens pertencem a cada grupo. Esta aula aborda esses cmdlets em detalhes, desde o uso básico até técnicas mais avançadas como ordenação por múltiplas propriedades e agrupamento com contagem.

Dominar esses cmdlets permite transformar saídas brutas em relatórios organizados e insights acionáveis. Por exemplo, você pode listar processos ordenados por uso de memória, agrupar arquivos por extensão e contar quantos arquivos de cada tipo existem em um diretório. Vamos explorar cada recurso com exemplos práticos.

Ordenação

O cmdlet Sort-Object ordena objetos com base em uma ou mais propriedades. Por padrão, a ordenação é ascendente. Você pode especificar a propriedade usando o parâmetro -Property (ou posicionalmente) e inverter a ordem com -Descending.

Exemplo: ordenar processos por nome (ascendente) e depois por ID (descendente).

Get-Process | Sort-Object Name, ID -Descending

Isso primeiro ordena por nome em ordem ascendente e, para processos com o mesmo nome, ordena por ID em ordem descendente. O parâmetro -Unique remove duplicatas com base na propriedade especificada (útil para listar valores únicos).

Get-Service | Sort-Object Status -Unique

Nesse caso, Sort-Object retorna apenas um objeto para cada valor único de Status (Running, Stopped, etc.), ordenando-os em ordem alfabética ascendente.

Por múltiplas propriedades

Para ordenar por várias propriedades, basta listá-las separadas por vírgula no parâmetro -Property. A ordem das propriedades define a prioridade: a primeira é a chave primária, a segunda é a secundária, e assim por diante.

Você pode combinar direções diferentes usando um array de hashtables com as chaves Expression e Ascending/Descending. Isso permite controle fino sobre cada nível de ordenação.

Get-ChildItem | Sort-Object @{Expression="Length"; Descending=$true}, @{Expression="Name"; Ascending=$true}

O exemplo acima ordena arquivos por tamanho (decrescente) e, para tamanhos iguais, por nome (crescente). Essa sintaxe é útil quando você precisa de direções diferentes para cada propriedade.

Agrupamento

O cmdlet Group-Object agrupa objetos que compartilham o mesmo valor em uma propriedade especificada. Ele retorna objetos com as propriedades Values (lista de itens no grupo), Count (número de itens) e Name (valor agrupado).

Exemplo: agrupar processos por nome do processo.

Get-Process | Group-Object ProcessName

Isso produz uma lista de grupos, cada um com o nome do processo e a contagem. Você pode acessar os itens individuais de um grupo usando a propriedade Group (sinônimo de Values).

Para agrupar por uma expressão, use o parâmetro -Property com um script block. Por exemplo, agrupar arquivos por extensão:

Get-ChildItem | Group-Object Extension

Isso agrupa arquivos por extensão (como .txt, .ps1, etc.) e mostra quantos arquivos de cada tipo existem.

Contagem

O agrupamento naturalmente fornece contagens através da propriedade Count de cada grupo. Para exibir apenas a contagem, você pode selecionar as propriedades Name e Count.

Get-Process | Group-Object ProcessName | Select-Object Name, Count

Para ordenar os grupos por contagem (do maior para o menor), combine com Sort-Object:

Get-Process | Group-Object ProcessName | Sort-Object Count -Descending | Select-Object -First 5

Isso mostra os 5 processos com mais instâncias em execução. Você também pode usar Measure-Object para contar itens sem agrupar, mas Group-Object já oferece a contagem embutida.

Referências

Exercícios

  1. Ordene a lista de serviços do sistema (Get-Service) por Status (Running primeiro) e depois por DisplayName (alfabético). Use uma única linha de comando.

    ✓ Resposta:
    Get-Service | Sort-Object Status -Descending, DisplayName

    Obs: Running vem antes de Stopped em ordem alfabética descendente (R > S).

  2. Agrupe os processos em execução pelo nome do processo e exiba apenas os grupos com mais de 3 instâncias. Dica: use Where-Object.

    ✓ Resposta:
    Get-Process | Group-Object ProcessName | Where-Object { $_.Count -gt 3 }
  3. Crie um comando que liste os 5 maiores arquivos no diretório atual (em tamanho), ordenados do maior para o menor. Use Sort-Object e Select-Object.

    ✓ Resposta:
    Get-ChildItem -File | Sort-Object Length -Descending | Select-Object -First 5
  4. Utilizando Group-Object, agrupe os eventos do log do sistema (Get-WinEvent -LogName System) por nível (LevelDisplayName) e exiba o nome do nível e a contagem, ordenado por contagem decrescente.

    ✓ Resposta:
    Get-WinEvent -LogName System | Group-Object LevelDisplayName | Sort-Object Count -Descending | Select-Object Name, Count

    Nota: Pode ser necessário executar como administrador.

  5. Ordene a lista de processos pelo consumo de memória (WorkingSet64) em ordem decrescente e, para processos com mesmo consumo, pelo nome em ordem crescente. Use a sintaxe de hashtable para direções diferentes.

    ✓ Resposta:
    Get-Process | Sort-Object @{Expression="WorkingSet64"; Descending=$true}, @{Expression="Name"; Ascending=$true}

Boas Práticas

Ao usar Sort-Object e Group-Object, lembre-se de que ambos consomem memória porque precisam processar toda a coleção antes de emitir resultados. Para coleções muito grandes, considere usar Select-Object -First para limitar a saída ou filtrar previamente com Where-Object. Sempre verifique se a ordenação ou agrupamento é realmente necessária para a tarefa.

Outra dica: use -CaseSensitive no Sort-Object e Group-Object quando a diferenciação entre maiúsculas e minúsculas for importante. Por padrão, a ordenação e o agrupamento não diferenciam maiúsculas de minúsculas.