Samstag, 4. April 2009

Get-Childitem an recursive comparing two directories

First let me tell you that I do my work from two different locations: the office and my home and I even spend some some hours in train without connection to the Internet.

Using offline files seems a good idea. Setting up folders for off-line use is easy and it works good while unconnected to the Internet.

The problems arise when connect to the office from home via VPN. You have no control whether synchronizing folders should happen or not, it just does. Sometimes the offline files stayed offline and inhibited me from connecting to my shares using the usual drive letters. Worst there is simple way to throw away offline files when they are in offline mode. I requires taken ownership of a lot of CSC files an deleting them.

Instaed of throwing bloody curses my final decision is not to use this halfbreed feature any more.

Copying some folders to my local disk is rather easy, but now I have to track somehow which files I changed and in which location .

I know of a tool WinMerge, which gives me all the control I need to sync folders, but it uses too much bandwidth. When the files at both locations have the same size an LastWriteTime then I have no need to compare the content.

One of the properties I missed when looking at the result from Get-ChildItem when using the recursive switch is, that it doesn't return the relative pathes and itherefore doesn't feed its results into Compare-Object in a simple way.

But PowerShell wouldn't be PowerShell, if there isn't a way to overcome the situation.

function Get-ChildItem2 ($path)
$PathLength = $path.length
gci $path -rec | % {
Add-Member -InputObject $_ -MemberType NoteProperty -Name RelativePath -Value $_.FullName.substring($PathLength+1)

this small little wrapper does the trick and all the fileobjects in the result are enhanced by a relativePath property.

Having two pathes $path1 and $path2 to folders you want to campare

Compare-Object (Get-ChildItem2 $path1) (Get-ChildItem2 $path2) -prop RelativePath, LastWriteTime, Length |
Sort RelativePath, LastWriteTime -desc | % {
if ($last -ne $_.RelativePath)
{ $_ }
$last = $_.RelativePath
} | sort RelativePath

gives a nice result telling which files are different and where you find the newer version.

The only thing, that me realy astonishes, is the fact, that I have to write this myself. It is so basic.


  1. One way to generate relative paths is with Split-Path, for example:

    dir | Add-Member ScriptProperty RelativePath {split-path $this.fullName -NoQualifier} -passThru

  2. Sorry that yields just the fullpath without the drivequalifier, independant of the current working directory.

  3. I can see what you mean, my bad :-)

  4. That doesn't matter. Any feedback, i.e. message that someone reads my blog is encouraging. I just tried to run gci on the remote filesystem. Much too slow. I must proceed to get Powershell running on the remote system.

  5. You know, there is a whole class of software that solves this problem (and others), source control systems.

  6. That is correct, part of my problems would disappear, if I would fetch the files from TFS directly to my local notebook drives and not to my official office shares.
    I think TFS SC does a rather effective job.