2

Can I change the output for SideIndicators as a result of Compare-Object to something more user friendly for standard users?

I have a script that compares the folder of a 2017 version of our software and the current 2018 version.

$var1 = Get-ChildItem -Recurse -path C:\software18\bin
$var2 = Get-ChildItem -Recurse -path C:\software17\bin
Compare-Object -ReferenceObject $var1 -DifferenceObject $var2 > C:\diff.txt

The output looks like this:

InputObject           SideIndicator
-----------           -------------
thing.dll                 =>
stuff.dll                 <=
software.exe              <=

The report is given to testers and it would be cleaner for them if I could change the SideIndicators into text.

My desired output:

InputObject           SideIndicator
-----------           -------------
thing.dll                Not in 18
stuff.dll                Not in 17
software.exe             Not in 17

Or something similiar where they can get the gist of it without having to know which is the reference/difference object.

I have an initial idea but searching for something similar doesn't yield many results. Don't know if I have to do an if loop or I can replace the brackets in PS. Still new to PS so I greatly appreciate the help!

mklement0
  • 382,024
  • 64
  • 607
  • 775
ATKiwi
  • 87
  • 1
  • 7

4 Answers4

7

You could loop over each object make a conditional for each side indicator:

$var1 = Get-ChildItem -Recurse -path C:\software18\bin
$var2 = Get-ChildItem -Recurse -path C:\software17\bin
(Compare-Object -ReferenceObject $var1 -DifferenceObject $var2 -PassThru |
    ForEach-Object {
        if ($_.SideIndicator -eq '=>') {
            $_.SideIndicator = 'Not in 18'
        } elseif ($_.SideIndicator -eq '<=')  {
            $_.SideIndicator = 'Not in 17'
        }
        $_
    }) > C:\diff.txt

Or you could just regex replace the strings in one step:

$var1 = Get-ChildItem -Recurse -path C:\software18\bin
$var2 = Get-ChildItem -Recurse -path C:\software17\bin
(Compare-Object -ReferenceObject $var1 -DifferenceObject $var2 -PassThru |
    ForEach-Object {
        $_.SideIndicator = $_.SideIndicator -replace '=>','Not in 18' -replace '<=','Not in 17'
        $_
    }) > C:\diff.txt
BenH
  • 9,766
  • 1
  • 22
  • 35
  • Tried both and my output was different. When I keep the `PassThru` parameters, the entire output was different (mode, last write). Also, it would not write to the txt file. I moved the write to into the last parenthesis but outsid the curly braces and that seemed to have worked. Thank! – ATKiwi May 31 '18 at 17:37
3

When storing the Reference/Difference sources into a variable instead of directly expanding you can replace the sideindicator with the path.

Based on BenHs answer:

$Ref = "C:\software18\bin"
$Dif = "C:\software17\bin"
(Compare-Object -Ref (ls -r $Ref) -Dif (ls -r $Dif)|
    ForEach-Object {
        if ($_.SideIndicator -eq '=>') {
            $_.SideIndicator = "Not in $Ref"
        } elseif ($_.SideIndicator -eq '<=')  {
            $_.SideIndicator = "Not in $Dif"
        }
        $_
    }
) > C:\diff.txt

Simulated output:

InputObject           SideIndicator
-----------           -------------
thing.dll             Not in C:\software18\bin
stuff.dll             Not in C:\software17\bin
software.exe          Not in C:\software17\bin
2

A long time ago, I wrote a script that uses compare-object to compare installed hotfixes across several machines in a cluster. http://get-powershell.com/post/2009/08/28/Comparing-Installed-Hotfixes-on-Servers.aspx

What I did was use a switch statement for different conditions of SideIndicator.

$comparedHotfixes = compare-object $server2HotFix $server1HotFix -IncludeEqual 

$result = @(); 

foreach ($c in $comparedHotfixes) { 
    $kbinfo = "" | select KB,$server1,$server2 
    $kbinfo.KB = $c.InputObject.HotfixId 
    switch ($c.SideIndicator) 
    { 
    "==" { 
            write-host -ForegroundColor Green "Both servers have $($c.InputObject.HotfixId)" 
            $kbinfo.($server1) = $true 
            $kbinfo.($server2) = $true 
            $result += $kbinfo 
         } 

    "=>" { 
            write-host -ForegroundColor Yellow "$server1 has $($c.InputObject.HotfixId) but $server2 doesn't" 
            $kbinfo.($server1) = $true 
            $kbinfo.($server2) = $false 
            $result += $kbinfo 
          } 

    "<="  { 
            write-host -ForegroundColor Magenta "$server2 has $($c.InputObject.HotfixId) but $server1 doesn't" 
            $kbinfo.($server1) = $false 
            $kbinfo.($server2) = $true 
            $result += $kbinfo 
          } 
    } # End Switch 
  } # End foreach 
Andy Schneider
  • 8,516
  • 6
  • 36
  • 52
2

A concise solution using Select-Object with a calculated property:

Compare-Object -ReferenceObject $var1 -DifferenceObject $var2 |
  Select-Object InputObject, @{ 
   n='SideIndicator';
   e={ @{ '<=' = 'Not in 18'; '=>' = 'Not in 17' }[$_.SideIndicator] }
  } > C:\diff.txt
mklement0
  • 382,024
  • 64
  • 607
  • 775