Wednesday, June 21, 2017

How to compare two folders in PowerShell by excluding some folders from source or destination

Today I  just came across a scenario where which I need bit to exclude some folder inside my parent folders while doing a comparison. I know there is  - Exclude for Get-ChildItem , but unfortunately this seems not working good for folders /file together and my scenario.

Finally  found a way to do this by using the below code, which exclude any folders in the regular expression.

Assume we have a folder  structure as below and we want to compare  “C:\ Source” and “D:\ Destination” recursively by excluding the files in D:\ XXXXXX and D:\ YYYYYY with any difference in XXXXXX.txt to be picked up.

C:
|Source
          |-XXXXXX
          |                 |File1.txt
          |                 |File2.txt
          |                 |File3.txt
          |-FolderA
          |                 |File4.txt
          |                 |File5.txt
          |                 |File6.txt
          |-FolderB
          |                 |File1.txt
          |                 |File2.txt
          |                 |File3.txt
          |- YYYYYY
          |                 |File1.txt
          |                 |File2.txt
          |                 |File3.txt
          |- XXXXXX.txt

 
D:
|Destination
          |- XXXXXX
          |                 |File1.txt
          |                 |File2.txt
          |                 |File3.txt
          |                 |File4.txt
          |-FolderA
          |                 |File4.txt
          |                 |File5.txt
          |                 |File6.txt
          |-FolderB
          |                 |File1.txt
          |                 |File2.txt
          |                 |File3.txt
          |- YYYYYY
          |                 |File1.txt
          |                 |File2.txt
          |                 |File3.txt
          |                 |File4.txt
          |- XXXXXX.txt

Below  code will fulfill the requirements. This will compare the source and destination folders by excluding any folders with name XXXXXX and YYYYYY. But this will also pick up any changes to files with same name in regular Expression Eg  XXXXXX.txt or YYYYYY.txt

Clear

#Arrive at the hash of destination folder by excluding the folders in regular expression "\w*\\XXXXXX\\\w*|\w*\\YYYYYY\\\w*"
$hashDestination=Get-ChildItem -Path "D:\temp\Destination" -Recurse | where {$_.FullName -notmatch  "\w*\\XXXXXX\\\w*|\w*\\YYYYYY\\\w*"  } |Get-FileHash -Algorithm "SHA256"

#Arrive at the hash of Source folder by excluding the folders in regular expression "\w*\\XXXXXX\\\w*|\w*\\YYYYYY\\\w*"
$hashSource=Get-ChildItem -Path "D:\temp\Source" -Recurse | where {$_.FullName -notmatch  "\w*\\XXXXXX\\\w*|\w*\\YYYYYY\\\w*"  } |Get-FileHash -Algorithm "SHA256"

$diff = 0
#Compare the hash we got  and increment $diff if we have a difference
Compare-Object -ReferenceObject $hashSource.Hash -DifferenceObject $hashDestination.Hash | % { If ($_.Sideindicator -ne " ==") {$diff+=1} }

#Check if $diff not equal to zero
If($diff -ne 0)
{
    #If yes, we have a difference
    return $true
}
else
{
    #If yes, we have a difference
    return $false
}

A much  mature version of the same logic can be found below. Which encapsulate the logic in reusable function Compare-Folders

clear
function Compare-Folders
{
    param(
        #Source Path Eg: "D:\temp\Source"
        $Source,
        #Destination Path Eg: "D:\temp\Destination"
        $Destination,
        #Regular Expression for Folder Exclusion Eg:"\w*\\YYYYYY\\\w*|\w*\\XXXXXX\\\w*"
        $ExcludeList
    )

    #Arrive at the hash of Source folder by excluding the folders in regular expression "\w*\\XXXXXX\\\w*|\w*\\YYYYYY\\\w*"
    $hashSource = Get-ChildItem -Path  $Source -Recurse | where {$_.FullName -notmatch  $ExcludeList  } |Get-FileHash -Algorithm "SHA256"

    #Arrive at the hash of destination folder by excluding the folders in regular expression "\w*\\XXXXXX\\\w*|\w*\\YYYYYY\\\w*"
    $hashDestination  = Get-ChildItem -Path  $Destination -Recurse | where {$_.FullName -notmatch  $ExcludeList  } |Get-FileHash -Algorithm "SHA256"

    $diff = 0
    #Compare the hash we got  and increment $diff if we have a difference
    Compare-Object -ReferenceObject $hashSource.Hash -DifferenceObject $hashDestination.Hash | % { If ($_.Sideindicator -ne " ==") {$diff+=1} }

    #Check if $diff not equal to zero
    If($diff -ne 0)
    {
        #If yes, we have a difference
        return $true
    }
    else
    {
        #If yes, we have a difference
        return $false
    }
}

 
$SourceFolder="D:\temp\Source"
$DestinationFolder="D:\temp\Destination"
#Compare the folders using the function
if(Compare-Folders -Source $SourceFolder -Destination $DestinationFolder -ExcludeList "\w*\\YYYYYY\\\w*|\w*\\XXXXXX\\\w*")
{
    Write-Host "Changes Found"
}
else
{
    Write-Host "No Changes Found"
}

No comments:

Post a Comment