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 is an IT veteran with over 25 years of experience, much of it spent as an IT infrastructure consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He is a multi-year recipient of the Microsoft MVP Award in Windows PowerShell. He works today as an independent author, trainer and consultant. Jeff has written for numerous online sites and print publications, is a contributing editor at Petri.com, and a frequent speaker at technology conferences and user groups.

comments powered by Disqus
Most   Popular