Prof. Powershell

Different Yet the Same

Compare-Object cmdlet tricks you might not know about.

I know I've mentioned the Compare-Object cmdlet before. It has an alias of diff. The cmdlet is handy when you need to -- what else? -- compare two different types of objects. Typically you want to compare a certain property. Here's a pretty standard example:

PS C:\> $now=get-process
PS C:\> calc
PS C:\> $after=get-process
PS C:\> diff $now $after -Property name

name                      SideIndicator
----                      -------------
calc                      =>


PS C:\>

The $now object is a snapshot of all the running processes. I then start Calculator and take another snapshot. Using Compare-Object I can identify the process that is running now that wasn't running earlier. The side indicator shows that. But what if I wanted to see more about the process, perhaps because I want to kill any processes running now that weren't running before. I need to tell Compare-Object to pass the entire object through to the pipeline.

PS C:\> diff $now $after -Property name -passthru

Handles  NPM(K)  PM(K)   WS(K)  VM(M)  CPU(s)    Id  ProcessName
-------  ------  -----   -----  -----  ------    --  -----------
     87       7   5496   11480     71    1.26  1724  calc

If I re-run this and pipe it to Get-Member I can verify that I am in fact getting a Process object. That makes a line this possible.

PS C:\> diff $now $after -Property name -passthru | kill

But let me show you a few other ways to use Compare-Object. I have two folders that I would like to keep sort of synchronized. Any file in FolderA should also be in FolderB. If there are extra files in FolderB, that's ok as long as it also has a copy of everything in FolderA Right now I can tell there is a discrepancy:

PS C:\> $a=dir f:\folderA
PS C:\> $b=dir f:\folderB
PS C:\> $a.count
77
PS C:\> $b.count
76
PS C:\>

For my example I'm only going to synchronize only by file name:

PS C:\> diff $a $b -property Name

name                      SideIndicator
----                      -------------
a.csv                     =>
b.csv                     =>
d.csv                     =>
w.txt                     <=
w1.txt                    <=
winrminfo.txt             <=
wmidata.txt               <=

But all I care about are files in $a that are not in $b. I could try filtering the output on the SideIndicator, but let's pass the objects through but only look at files in FolderA:

PS C:\> diff $a $b -property Name -pass | Where {$_.DirectoryName -eq "F:\folderA"}

   Directory: F:\folderA

Mode            LastWriteTime   Length Name
----            -------------   ------ ----
-a---    5/14/2009    4:38 PM      863 w.txt
-a---    5/14/2009    4:42 PM      266 w1.txt
-a---     3/3/2009   12:41 PM    63538 winrminfo.txt
-a---     3/21/2009   4:47 PM    96786 wmidata.txt

These files need to be added to FolderB:

PS C:\> diff $a $b -property Name -pass | Where {$_.DirectoryName -eq "F:\folderA"} | copy -dest f:\folderb -passthru

   Directory: F:\folderb

Mode            LastWriteTime   Length Name
----            -------------   ------ ----
-a---    5/14/2009    4:38 PM      863 w.txt
-a---    5/14/2009    4:42 PM      266 w1.txt
-a---     3/3/2009   12:41 PM    63538 winrminfo.txt
-a---     3/21/2009   4:47 PM    96786 wmidata.txt

All I had to do was pipe the file objects to Copy-Object. I used its -passthru parameter as well so I could see the results. Now all the files in FolderA can also be found in FolderB. It wouldn't take much more to synchronize both ways but I'll leave that exercise to you.


About the Author

Jeffery Hicks (MCSE,MCSA,MCT) is a Microsoft MVP and an IT veteran with almost 20 years of experience, much of it spent as an IT consultant specializing in Windows server technologies. He works today as an independent author, trainer and consultant. Jeff has co-authored or authored several books, courseware, and training videos on administrative scripting and automation. His latest book is Managing Active Directory with Windows PowerShell: TFM (SAPIEN Press 2008). You can follow Jeff at twitter.com/jeffhicks and jdhitsolutions.com/blog.

Reader Comments:

Add Your Comment Now:

Your Name:(optional)
Your Email:(optional)
Your Location:(optional)
Comment:
Please type the letters/numbers you see above