Scripting Games 2012 comments: #8 Beginners Event 4

http://blogs.technet.com/b/heyscriptingguy/archive/2012/04/05/2012-scripting-games-beginner-event-4-compare-two-folders.aspx

Makes sure you run the script provided with the event to get the right folders. The script randomly removes 1 file from each folder – sneaky.

After last nights head scratching this one is much simpler. It’s solvable with one line of PowerShell.

For this one we have a data folder and a back up folder we need to compare. 

Requirements:

  • Content of backup folder is same as data folder
  • Only compare file names
  • Show files in one folder that don't exist in other
  • Return file information objects as result of comparison
  • Don't need complicated script
  • Unnecessary complexity costs points
  • Extra points for native PowerShell cmdlets and code simplicity

We need to deal with file names – so that implies Get-ChildItem.  We can see the contents of the files:

Get-ChildItem -Path c:\1
Get-ChildItem -Path c:\2

Do we have anything to do a compare?

Get-Command *compare*

shows we have compare-object.

If you haven’t seen this before – read the help.

In fact as a general rule read the help for all cmdlets before using in the games just to make sure you understand them and you’ve picked up on all the extras that might help you.

PS> get-help Compare-Object

SYNOPSIS
    Compares two sets of objects.


SYNTAX
    Compare-Object [-ReferenceObject] <PSObject[]> [-DifferenceObject] <PSObject[]>
   [-CaseSensitive] [-Culture <string>  ] [-ExcludeDifferent] [-IncludeEqual] [-PassThru]
   [-Property <Object[]>] [-SyncWindow <int>] [<CommonParameters>]


DESCRIPTION
    The Compare-Object cmdlet compares two sets of objects. One set of objects is the Reference set,
    and the other set is the Difference set.

    The result of the comparison indicates whether a property value appeared only in the object from
    the Reference set (indicated by the <= symbol), only in the object from the Difference set
   (indicated by the => symbol) or, if the IncludeEqual parameter is specified, in both objects
   (indicated by the == symbol).

 

This means we need to treat the folder contents as objects. PowerShell has a very clever trick we can use here. We put the

Get-ChildItem -Path c:\1
Get-ChildItem -Path c:\2

in parentheses which tells PowerShell to treat them as objects and we can use these directly as input to compare-object.

PS> Compare-Object -ReferenceObject (Get-ChildItem -Path c:\1) -DifferenceObject (Get-ChildItem -Path c:\2)

InputObject                                                 SideIndicator
-----------                                                 -------------
13.txt                                                      =>
10.txt                                                      <=

That should make sense now you can see what I mean. The alternative would be to do this

PS> $list1 = Get-ChildItem -Path c:\1
PS> $list2 = Get-ChildItem -Path c:\2
PS> Compare-Object -ReferenceObject $list1 -DifferenceObject $list2

InputObject                                                 SideIndicator
-----------                                                 -------------
13.txt                                                      =>
10.txt                                                      <=

which involves more typing and depending on how you define complexity is more complex.

We can do the compare but we need to restrict the comparison to file names – so we need the –Property parameter.  This is why you need to read the help file.

Compare-Object -ReferenceObject (Get-ChildItem -Path c:\1) -DifferenceObject (Get-ChildItem -Path c:\2)  -Property Name

This still produces the output above and we were told to output file objects. Once more into the help file and we find –Passthru which “Passes the objects that differed to the pipeline. By default, this cmdlet does not generate any output.”

PS> Compare-Object -ReferenceObject (Get-ChildItem -Path c:\1) -DifferenceObject (Get-ChildItem -Path c:\2)  -Property Name -PassThru


    Directory: C:\2


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        14/04/2012     15:54          0 13.txt


    Directory: C:\1


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        14/04/2012     15:54          0 10.txt

That solves the problem and is as simple as it gets. Oh you want aliases as well.

compare -R (ls c:\1) -Di (ls c:\2)  -Pr Name –Pa

And that is why I don’t like aliases because it is no where near as obvious what I am doing.

Leave a Reply