Chapter 22. Comparing Data

Introduction

When working in PowerShell, it is common to work with collections of objects. Most PowerShell commands generate objects, as do many of the methods that you work with in the .NET Framework. To help you work with these object collections, PowerShell introduces the Compare-Object cmdlet. The Compare-Object cmdlet provides functionality similar to the well-known diff commands, but with an object-oriented flavor.

Compare the Output of Two Commands

Problem

You want to compare the output of two commands.

Solution

To compare the output of two commands, store the output of each command in variables, and then use the Compare-Object cmdlet to compare those variables:

PS > notepad
PS > $processes = Get-Process
PS > Stop-Process -ProcessName Notepad
PS > $newProcesses = Get-Process
PS > Compare-Object $processes $newProcesses

InputObject                           SideIndicator
-----------                           -------------
System.Diagnostics.Process (notepad)  <=

Discussion

The Solution shows how to determine which processes have exited between the two calls to Get-Process. The SideIndicator of <= tells us that the process was present in the left collection ($processes) but not in the right ($newProcesses). To work with the actual object that was different, access the InputObject property:

PS > $diff = @(Compare-Object $processes $newProcesses)[0]
PS > $process = $diff.InputObject
PS > $process.Handles
55

By default, the Compare-Object cmdlet uses the comparison functionality built into most .NET objects. This works as expected most of the time, but sometimes you might want to override that comparison behavior. For example, you might want two processes to be considered different if their memory usage changes. In that case, use the -Property parameter.

PS > Compare-Object $processes $newProcesses -Property Name,WS | Sort Name

Name                                           WS SideIndicator
----                                           -- -------------
dwm                                      31358976 <=
dwm                                      29540352 =>
explorer                                 37969920 <=
explorer                                 38023168 =>
lsass                                     1548288 =>
lsass                                     1372160 <=
notepad                                   5701632 <=
notepad                                   2891776 =>
powershell                               44281856 =>
powershell                               44290048 <=
SearchIndexer                            13606912 =>
SearchIndexer                            13619200 <=
svchost                                  56061952 <=
svchost                                  43982848 <=
svchost                                  56037376 =>
svchost                                  44048384 =>
svchost                                  12193792 <=
svchost                                  12201984 =>
taskeng                                   9220096 <=
taskeng                                   9228288 =>

When you use the -Property parameter, the Compare-Object cmdlet outputs custom objects that have only the properties you used in the comparison. If you still want access to the original objects used in the comparison, also use the -PassThru parameter. In that case, PowerShell instead adds the SideIndicator property to the original objects.

Note

If the objects you are comparing are already in proper order (for example, the lines in a file), you can improve the performance of the comparison process by using the -SyncWindow parameter. A sync window of five, for example, looks for differences only within the surrounding five objects.

For more information about the Compare-Object cmdlet, type Get-Help Compare-Object.

Determine the Differences Between Two Files

Problem

You want to determine the differences between two files.

Solution

To determine simple differences in the content of each file, store their content in variables, and then use the Compare-Object cmdlet to compare those variables:

PS > "Hello World" > c:	empfile1.txt
PS > "Hello World" > c:	empfile2.txt
PS > "More Information" >> c:	empfile2.txt
PS > $content1 = Get-Content c:	empfile1.txt
PS > $content2 = Get-Content c:	empfile2.txt
PS > Compare-Object $content1 $content2

InputObject                              SideIndicator
-----------                              -------------
More Information                         =>

Discussion

The primary focus of the Compare-Object cmdlet is to compare two unordered sets of objects. Although those sets of objects can be strings (as in the content of two files), the output of Compare-Object when run against files is usually counterintuitive because of the content losing its order.

When comparing large files (or files where the order of comparison matters), you can still use traditional file comparison tools such as diff.exe or the WinDiff application that comes with both the Windows Support Tools and Visual Studio.

For more information about the Compare-Object cmdlet, type Get-Help Compare-Object.

Verify Integrity of File Sets

Problem

You want to determine whether any files in a set of files have been modified or damaged.

Solution

To verify the integrity of file sets, use the Get-FileHash script provided in Program: Get the MD5 or SHA1 Hash of a File to generate the signatures of those files in question. Do the same for the files on a known good system. Finally, use the Compare-Object cmdlet to compare those two sets.

Discussion

To generate the information from the files in question, use a command like:

dir C:WindowsSystem32WindowsPowerShellv1.0 | Get-FileHash |
    Export-CliXml c:	empPowerShellHashes.clixml

This command gets the hash values of the files from C:WindowsSystem32 WindowsPowerShellv1.0, and uses the Export-CliXml cmdlet to store that data in a file.

Transport this file to a system with files in a known good state, and then import the data from that file.

$otherHashes = Import-CliXml c:	empPowerShellHashes.clixml

Note

You can also map a network drive to the files in question and skip the export, transport, and import steps altogether:

net use x: \lee-deskc$WindowsSystem32WindowsPowerShellv1.0
$otherHashes = dir x: | Get-FileHash

Generate the information from the files you know are in a good state:

$knownHashes = dir C:WindowsSystem32WindowsPowerShellv1.0 |
    Get-FileHash

Finally, use the Compare-Object cmdlet to detect any differences:

Compare-Object $otherHashes $knownHashes -Property Path,HashValue

If there are any differences, the Compare-Object cmdlet displays them in a list, as shown in Example 22-1.

Example 22-1. The Compare-Object cmdlet showing differences between two files

PS > Compare-Object $otherHashes $knownHashes -Property Path,HashValue
Path                     HashValue                SideIndicator
----                     ---------                -----------------------
system.management.aut... 247F291CCDA8E669FF9FA... =>
system.management.aut... 5A68BC5819E29B8E3648F... <=


PS > Compare-Object $otherHashes $knownHashes -Property Path,HashValue |
Select-Object Path


Path
----
system.management.automation.dll-help.xml
system.management.automation.dll-help.xml

For more information about the Compare-Object cmdlet, type Get-Help Compare-Object. For more information about the Export-CliXml and Import-CliXml cmdlets, type Get-Help Export-CliXml and Get-Help Import-CliXml, respectively.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.189.180.43