Comparando objetos
Esta aula ensina a comparar objetos no PowerShell usando o cmdlet Compare-Object. Você aprenderá a identificar diferenças entre coleções, entender os parâmetros disponíveis e aplicar o comando em casos práticos como sincronização de arquivos e validação de dados.
Comparar objetos é uma tarefa comum na administração de sistemas e automação. No PowerShell, o cmdlet Compare-Object permite comparar duas coleções de objetos e identificar as diferenças entre elas. Ele é útil para verificar se dois conjuntos de dados são iguais, encontrar itens que existem em apenas uma das listas ou detectar mudanças ao longo do tempo.
Nesta aula, vamos explorar o funcionamento do Compare-Object, seus parâmetros e como interpretar os resultados. Veremos exemplos práticos que demonstram seu uso em cenários reais, como comparação de arquivos, usuários e processos.
Compare-Object
O cmdlet Compare-Object compara dois conjuntos de objetos: um conjunto de referência (-ReferenceObject) e um conjunto de diferença (-DifferenceObject). Ele retorna objetos que indicam quais itens estão presentes em apenas um dos conjuntos ou em ambos. A saída inclui uma propriedade SideIndicator que mostra de que lado o item é único: <= indica que o item está apenas no conjunto de referência, => indica que está apenas no conjunto de diferença.
A sintaxe básica é:
Compare-Object -ReferenceObject @(1,2,3) -DifferenceObject @(2,3,4)Isso retornaria:
InputObject SideIndicator
----------- -------------
1 <=
4 =>Por padrão, a comparação é feita por valor, mas você pode especificar propriedades com o parâmetro -Property para comparar objetos complexos.
Diferenças
As diferenças são identificadas através do SideIndicator. Existem três possibilidades:
<=: O item está apenas no conjunto de referência (lado esquerdo).=>: O item está apenas no conjunto de diferença (lado direito).- Sem indicador (se usar
-IncludeEqual): O item está presente em ambos os conjuntos.
Você pode personalizar a comparação com vários parâmetros:
-ExcludeDifferent: Exibe apenas os itens iguais.-IncludeEqual: Inclui itens iguais na saída.-PassThru: Passa os objetos originais em vez de objetosCompare-Object, útil para encadear comandos.-CaseSensitive: Torna a comparação sensível a maiúsculas/minúsculas.-SyncWindow: Define o número de elementos para sincronização em comparações sequenciais.
Por exemplo, para incluir itens iguais:
Compare-Object -ReferenceObject @(1,2,3) -DifferenceObject @(2,3,4) -IncludeEqualSaída:
InputObject SideIndicator
----------- -------------
1 <=
2 ==
3 ==
4 =>Casos de uso
O Compare-Object é amplamente utilizado em scripts de automação e administração. Alguns casos comuns:
- Sincronização de arquivos: Comparar listas de arquivos em duas pastas para identificar quais precisam ser copiados ou removidos.
- Validação de configurações: Comparar configurações atuais com um baseline para detectar alterações.
- Gerenciamento de usuários: Comparar listas de usuários de dois sistemas (ex.: AD vs CSV) para encontrar discrepâncias.
- Testes de software: Verificar se a saída de um comando corresponde ao esperado.
- Auditoria de alterações: Comparar snapshots de estado do sistema em momentos diferentes.
Por exemplo, para comparar dois arquivos CSV:
$csv1 = Import-Csv -Path "C:\dados1.csv"
$csv2 = Import-Csv -Path "C:\dados2.csv"
Compare-Object -ReferenceObject $csv1 -DifferenceObject $csv2 -Property "Nome","Idade"Exemplos
Exemplo 1: Comparar arrays simples
$ref = @(10,20,30)
$diff = @(20,30,40)
Compare-Object -ReferenceObject $ref -DifferenceObject $diffSaída:
InputObject SideIndicator
----------- -------------
10 <=
40 =>Exemplo 2: Comparar objetos com propriedades
$user1 = [PSCustomObject]@{Name="Alice"; Age=30}
$user2 = [PSCustomObject]@{Name="Bob"; Age=25}
$user3 = [PSCustomObject]@{Name="Alice"; Age=30}
Compare-Object -ReferenceObject $user1 -DifferenceObject $user2,$user3 -Property Name,AgeSaída:
Name Age SideIndicator
---- --- -------------
Bob 25 =>
Alice 30 ==Exemplo 3: Comparar listas de arquivos
$pastas1 = Get-ChildItem -Path "C:\pastaA" -File
$pastas2 = Get-ChildItem -Path "C:\pastaB" -File
Compare-Object -ReferenceObject $pastas1 -DifferenceObject $pastas2 -Property Name,LengthIsso mostra arquivos que diferem em nome ou tamanho entre as pastas.
Exemplo 4: Usar -PassThru para processar objetos originais
$ref = Get-Process -Name "notepad"
$diff = Get-Process -Name "notepad","calc"
Compare-Object -ReferenceObject $ref -DifferenceObject $diff -PassThru | Where-Object {$_.SideIndicator -eq "=>"} | Stop-ProcessIsso para processos que estão apenas no conjunto de diferença (calc).
Boas práticas
- Sempre especifique
-Propertyao comparar objetos complexos para evitar comparações por referência. - Use
-IncludeEqualquando quiser confirmar que não há diferenças. - Combine
Compare-ObjectcomWhere-ObjecteForEach-Objectpara ações baseadas nas diferenças. - Para grandes conjuntos de dados, considere usar
HashSetou índices para melhor desempenho.
Referências
- Documentação oficial do Compare-Object
- Exemplos da Microsoft sobre comparação de objetos
- SS64: Compare-Object
- Petri: Using Compare-Object in PowerShell
- PowerShell.org: Comparing Objects with PowerShell
Exercícios
Crie dois arrays com números de 1 a 5 e de 3 a 7. Use Compare-Object para exibir os números que estão apenas no primeiro array.
✓ Resposta:$arr1 = 1..5 $arr2 = 3..7 Compare-Object -ReferenceObject $arr1 -DifferenceObject $arr2 | Where-Object {$_.SideIndicator -eq "<="}Compare dois objetos personalizados com as propriedades Nome e Idade. Inclua os itens iguais na saída.
✓ Resposta:$obj1 = [PSCustomObject]@{Nome="João"; Idade=30} $obj2 = [PSCustomObject]@{Nome="Maria"; Idade=25} $obj3 = [PSCustomObject]@{Nome="João"; Idade=30} Compare-Object -ReferenceObject $obj1 -DifferenceObject $obj2,$obj3 -Property Nome,Idade -IncludeEqualUtilize Compare-Object para listar os processos que estão em execução no momento atual, mas não estavam há 5 segundos (simule dois snapshots).
✓ Resposta:$snapshot1 = Get-Process Start-Sleep -Seconds 5 $snapshot2 = Get-Process Compare-Object -ReferenceObject $snapshot1 -DifferenceObject $snapshot2 -Property Id,ProcessName | Where-Object {$_.SideIndicator -eq "=>"}Compare duas listas de arquivos em pastas diferentes e exiba apenas os arquivos que estão na primeira pasta mas não na segunda (considere nome e tamanho).
✓ Resposta:$pastaA = Get-ChildItem -Path "C:\PastaA" -File $pastaB = Get-ChildItem -Path "C:\PastaB" -File Compare-Object -ReferenceObject $pastaA -DifferenceObject $pastaB -Property Name,Length | Where-Object {$_.SideIndicator -eq "<="}Crie um script que use Compare-Object para verificar se dois arquivos CSV (com colunas Nome e Email) são idênticos. Exiba uma mensagem se forem iguais ou liste as diferenças.
✓ Resposta:$csv1 = Import-Csv -Path "C:\dados1.csv" $csv2 = Import-Csv -Path "C:\dados2.csv" $diferencas = Compare-Object -ReferenceObject $csv1 -DifferenceObject $csv2 -Property Nome,Email if ($diferencas) { Write-Host "Diferenças encontradas:" $diferencas } else { Write-Host "Os arquivos são idênticos." }