1

I am a newbie in PowerShell, and trying to learn the things from few forums and msdn. Now i got some requirement from my group of learners.

I am trying to compare 2 folder's files with each other in powershell, for effective file comparison i am using MD5 Hashes. Till now i have created a code like this,

[Cmdletbinding()]
Param
(
[Parameter(Position=0, Mandatory)][ValidateScript({ Test-Path -Path $_ })][string]$SourceFolder,
[Parameter(Position=1, Mandatory)][ValidateScript({ Test-Path -Path $_ })][string]$DestinationFolder
) 
$SourceFolderList =@()
$DestinationFolderList =@()

$Sourcefiles = @(Get-ChildItem -Path $SourceFolder -Filter *.log)
foreach($srcFile in $Sourcefiles )
{
    $SourceFolderHash = [ordered]@{}
    $SourceFolderHash.Name = $srcFile.Name
    $SourceFolderHash.FullName = $srcFile.FullName
    $obj = New-Object PSObject -Property $SourceFolderHash
    $SourceFolderList+= $obj
}

$Destfiles = @(Get-ChildItem -Path $DestinationFolder -Filter *.log)
foreach($Destfile in $Destfiles )
{
    $DestinationFolderHash = [ordered]@{}
    $DestinationFolderHash.Name = $Destfile.Name
    $DestinationFolderHash.FullName = $Destfile.FullName
    $obj = New-Object PSObject -Property $DestinationFolderHash
    $DestinationFolderList+= $obj
}

$SourceFolderList =@() & $DestinationFolderList =@() are Arrays with Name & FullName properties.

Now i am trying to create a new array with values which matches in the $SourceFolderList & $DestinationFolderList ( I hope i am going in the right way?!)

But the problem is, i am not sure how to loop through each item in the Arrays and get the fullnames of each file from 2 folders to pass as params to MD5hash Function.

I am trying in this way

##1
For ($i =$j=0; $i -le $SourceFolderList.Count -and $j -le $DestinationFolderList.Count; $i++ -and $j++)
 {
    $file1Name = $SourceFolderList[$i].Name 
    $file1Path = $SourceFolderList[$i].FullName 

    $file2Name = $DestinationFolderList[$j].Name 
    $file2Path = $DestinationFolderList[$j].FullName  
 }

##2
foreach( $file in $SourceFolderList)
{
    if($DestinationFolderList.Name  -contains $file.Name )
    {
        Write-Host  $file.Name -ForegroundColor Cyan 
        Write-Host  $DestinationFolderList.($file.Name).FullName -ForegroundColor Yellow
    }
}

In the 1st way i am not getting correct File Paths << Index is mismatching for Destination folder's file paths >>

In the 2nd Way i am not at all getting the Full Path of file.

Please correct me if am going in the wrong way to achieve my requirement. And please help me to solve this issue.

Naren_Ch
  • 35
  • 7
  • possible duplicate of [Comparing folders and content with PowerShell](http://stackoverflow.com/questions/6526441/comparing-folders-and-content-with-powershell) – Loïc MICHEL Sep 18 '15 at 13:26

1 Answers1

1

I think your're making your task more difficult that it is, by gathering file info into the arrays. Why don't you just iterate over the files in the source folder and compare their hashes with hashes of files in the destination folder on the fly:

function Compare-Folders
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [string]$Source,

        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [string]$Destinaton,

        [Parameter(ValueFromPipelineByPropertyName = $true)]
        [string]$Filter
    )

    Process
    {
        # Iterate over files in source folder, skip folders
        Get-ChildItem -Path $Source -Filter $Filter | Where-Object {!$_.PsIsContainer} | ForEach-Object {
            # Generate file name in destination folder
            $DstFileName = Resolve-Path -Path (Join-Path -Path $Destinaton -ChildPath (Split-Path -Path $_.FullName -Leaf))

            # Create hashtable with filenames and hashes
            $Result = @{
                SourceFile = $_.FullName
                SourceFileHash = (Get-FileHash -Path $_.FullName -Algorithm MD5).Hash
                DestinationFile = $DstFileName
                DestinationFileHash = (Get-FileHash -Path $DstFileName -Algorithm MD5).Hash
            }

            # Check if file hashes are equal and add result to hashtable
            $Result.Add('IsEqual', ($Result.SourceFileHash -eq $Result.DestinationFileHash))

            # Output PsObject from hashtable
            New-Object -TypeName psobject -Property $Result |
                Select-Object -Property SourceFile, SourceFileHash , DestinationFile, DestinationFileHash, IsEqual
        }
    }
}
beatcracker
  • 6,714
  • 1
  • 18
  • 41
  • Thanks for the reply @beatcracker, – Naren_Ch Sep 18 '15 at 14:08
  • Actually i don't sure about the easiest and effective way of doing this task, i though it would be easy and we can use the props if we create 3rd array from the two file list Arrays. – Naren_Ch Sep 18 '15 at 14:14
  • I am getting below error `Exception calling "Create" with "1" argument(s): "This implementation is not part of the Windows Platform FIPS validated cryptographic algorithms." At C:\windows\system32\windowspowershell\v1.0\Modules\Microsoft.PowerShell.Util ity\Microsoft.PowerShell.Utility.psm1:26 char:9 + $hasher = [System.Security.Cryptography.HashAlgorithm]::Create($Algorith ... ` get-Filehash is not working on my winserver2012R2 , where as its working in win8 Os, pls tell me what I've to do. – Naren_Ch Sep 18 '15 at 14:17
  • @Naren_Ch You have "FIPS Compliant Algorithms" enabled on your server. MD5 is not FIPS compliant. So either [Disable FIPS Compliant Algorithms](http://docs.trendmicro.com/all/ent/sc/v3.0/en-US/cmcolh/t_fips.html) or use another hash algorithm in `Get-FileHash` cmdlet. – beatcracker Sep 18 '15 at 14:44
  • Okay. Can i use any algorithm in this case. Does that produce correct hash for the file comparision?! If yes, then the problem is solved.. – Naren_Ch Sep 18 '15 at 16:41
  • @Naren_Ch You can just remove `-Algorithm MD5` argument altogether and `Get-FileHash` will use `SHA256` by default, which is much stronger hash function than `MD5`. – beatcracker Sep 18 '15 at 16:44