# encoding: ascii
# api: powershell
# title: Sync Files and Folders
# description: Sync Files and Folders with powershell
# version: 0.1
# type: script
# author: SyncFolder
# license: CC0
# function: Copy-LatestFile
# x-poshcode-id: 6239
# x-archived: 2017-03-18T15:33:23
# x-published: 2017-02-28T11:03:00
#
#
param ( 
   [Parameter(Mandatory=$true,HelpMessage= "Enter souce folder path")] 
   [ValidateScript({Test-Path $_ -PathType Container})] 
   [string]$Src, 
   [Parameter(Mandatory=$true,HelpMessage= "Enter destination folder path")] 
   [ValidateScript({Test-Path $_ -PathType Container})] 
   [string]$Dst 
    
)

# Function to copy files according to last Modified date
function Copy-LatestFile { 
   Param( 
      [string]$File1, 
      [string]$File2, 
      [switch]$WhatIf 
   ) 
   $File1Date = Get-Item $File1 | Foreach-Object {$_.LastWriteTimeUTC} 
   $File2Date = Get-Item $File2 | Foreach-Object {$_.LastWriteTimeUTC} 
   if ($File1Date -gt $File2Date) { 
      Write-Host "$File1 is newer than $File2, performing copy." 
      if($WhatIf) { 
         Copy-Item $File1 $File2 -Force -WhatIf 
      } else { 
         Copy-Item $File1 $File2 -Force 
      } 
   } else { 
      Write-Host "$File2 is newer than $File1, performing copy." 
      if ($whatif) { 
         Copy-Item $File2 $File1 -Force -WhatIf 
      } else { 
         Copy-Item $File2 $File1 -Force 
      } 
   } 
   Write-Host 
} 
if(-Not(Test-Path $Destination)) { 
   New-Item $Destination -Type Directory -Force | Out-Null 
} 

# Getting Files/Folders from Source and Destination 
$SrcEntries = Get-ChildItem $Source -Recurse 
$DstEntries = Get-ChildItem $Destination -Recurse 

# Parsing the folders and Files from Collections 
$SrcFolders = $SrcEntries | Where-Object{$_.PSIsContainer} 
$SrcFiles = $SrcEntries | Where-Object{!$_.PSIsContainer} 
$DstFolders = $DstEntries | Where-Object{$_.PSIsContainer} 
$DstFiles = $DstEntries | Where-Object{!$_.PSIsContainer} 

# Checking for Folders that exist in Source, but are missing from Destination 
foreach ($Folder in $Srcfolders) { 
   $SrcFolderPath = $Source -replace "\\","\\" -replace "\:","\:" 
   $DstFolder = $Folder.Fullname -replace $SrcFolderPath,$Destination 
   if($DstFolder -ne "") { 
      if(-Not(Test-Path $DstFolder)) { 
         Write-Warning "Folder $DstFolder does not exist. Creating $DstFolder." 
         New-Item $DstFolder -Type Directory | Out-Null 
      } 
   } 
} 

# Checking for Folders that exist in Destinatinon, but are missing from Source 
foreach ($Folder in $DestFolders) { 
   $DstFilePath = $Destination -replace "\\","\\" -replace "\:","\:" 
   $SrcFolder = $Folder.Fullname -replace $DstFilePath,$Source 
   if ($srcFolder -ne "") { 
      if(-Not(Test-Path $SrcFolder)) { 
         Write-Warning "Folder $SrcFolder does not exist. Creating $SrcFolder." 
         New-Item $SrcFolder -Type Directory | Out-Null 
      } 
   } 
} 

# Checking for Files that exist in Source, but are missing from Destination 
foreach ($Entry in $SrcFiles) { 
   $SrcFullname = $Entry.FullName 
   $SrcName = $Entry.Name 
   $SrcFilePath = $Source -replace "\\","\\" -replace "\:","\:" 
   $DstFile = $SrcFullname -replace $SrcFilePath,$Destination 
   if(Test-Path $DstFile) { 
      $SrcMD5 = (Get-FileHash $SrcFullname).Hash 
      $DstMD5 = (Get-FileHash $DstFile).Hash 
      if ($SrcMD5 -ne $DstMD5) { 
         Write-Warning "File MD5 checksums do not match, deciding by last modified date." 
         Write-Host "MD5: $SrcMD5 File: $SrcFullname" 
         Write-Host "MD5: $DstMD5 File: $DstFile" 
         Copy-LatestFile $SrcFullname $DstFile 
      } 
   } else { 
      Write-Host "$DstFile does not exist, copying from $SrcFullname" 
      Copy-Item $SrcFullName $DstFile -Force 
   } 
} 

# Checking for Files that exist in Destinatinon, but are missing from Source 
foreach ($Entry in $DesFiles) { 
   $DstFullname = $entry.FullName 
   $DstName = $Entry.Name 
   $DstFilePath = $Destination -replace "\\","\\" -replace "\:","\:" 
   $SrcFile = $DstFullname -replace $DstFilePath,$Source 
   if ($SrcFile -ne "") { 
      if (-Not(Test-Path $SrcFile)) { 
         Write-Host "File $SrcFile does not exist, copying from $DstFullname." 
         Copy-Item $DstFullname $SrcFile -Force 
      } 
   } 
}
