PoshCode Logo PowerShell Code Repository

Start-FolderSync by M Skourlatov 2 weeks ago
embed code: <script type="text/javascript" src="http://PoshCode.org/embed/6890"></script>download | new post

Small script to strongly syncronyze folder with ‘original’.

  1. Add-Type -TypeDefinition @"
  2.  
  3. public struct HashContainer : System.IComparable
  4. {
  5.         public ulong High;
  6.         public ulong Low;
  7.  
  8.         public HashContainer(byte[] Buffer)
  9.         {
  10.                 System.Array.Reverse(Buffer);
  11.                 this.Low = System.BitConverter.ToUInt64(Buffer, 0);
  12.                 this.High = System.BitConverter.ToUInt64(Buffer, 8);
  13.         }
  14.  
  15.         public int CompareTo(object obj)
  16.         {
  17.                 if (obj == null) { return 1; }
  18.                 var other = (HashContainer)obj;
  19.  
  20.                 int compare = this.High.CompareTo(other.High);
  21.                 if (compare != 0) return compare;
  22.                 return this.Low.CompareTo(other.Low);
  23.         }
  24.  
  25.         public override string ToString()
  26.         {
  27.                 return string.Format("{0:X}{1:X}", this.High, this.Low);
  28.         }
  29.  
  30. }
  31.  
  32. public class FIComparable : System.IComparable
  33. {
  34.         public System.IO.FileInfo Info;
  35.  
  36.         private bool hasHash;
  37.         private HashContainer hash;
  38.  
  39.         public FIComparable(System.IO.FileInfo info)
  40.         {
  41.                 this.Info = info;
  42.                 this.hasHash = false;
  43.         }
  44.  
  45.         public HashContainer GetHash()
  46.         {
  47.                 if (this.hasHash) { return this.hash; }
  48.  
  49.                 var crypto = new System.Security.Cryptography.MD5CryptoServiceProvider();
  50.                 var stream = new System.IO.FileStream(
  51.                         this.Info.FullName,
  52.                         System.IO.FileMode.Open,
  53.                         System.IO.FileAccess.Read,
  54.                         System.IO.FileShare.None);
  55.                 var buf = crypto.ComputeHash(stream);
  56.                 stream.Close();
  57.  
  58.                 this.hash = new HashContainer(buf);
  59.                 this.hasHash = true;
  60.                 return this.hash;
  61.         }
  62.  
  63.         public int CompareTo(object obj)
  64.         {
  65.                 if (obj == null) { return 1; }
  66.                 var other = obj as FIComparable;
  67.  
  68.                 if (null != other)
  69.                 {
  70.                         int compare = this.Info.Name.CompareTo(other.Info.Name);
  71.                         if (compare != 0) { return compare; }
  72.                         compare = this.Info.Length.CompareTo(other.Info.Length);
  73.                         if (compare != 0) { return compare; }
  74.                         return this.GetHash().CompareTo(other.GetHash());
  75.                 }
  76.                 else { throw new System.ArgumentException(); }
  77.         }
  78.        
  79.         public override string ToString() { return this.Info.Name; }
  80. }
  81. "@
  82.  
  83. Function Start-FolderSync
  84. {
  85.         Param
  86.         (
  87.                 [parameter(Mandatory, Position = 0)]
  88.                 [ValidateScript({ Test-Path -Path $_ -PathType 'Container' })]
  89.                 [string]$Reference,
  90.                 [parameter(Mandatory, Position = 1)]
  91.                 [string]$Synchronized
  92.         )
  93.  
  94.         function Get-Comparable($list)
  95.         {
  96.                 $sync = New-Object 'System.Collections.Generic.List[FIComparable]'
  97.                 foreach ($item in $list) { $sync.Add((New-Object FIComparable $item)) }
  98.                 return $sync
  99.         }
  100.  
  101.         $gotcha = Get-ChildItem -LiteralPath $Reference
  102.         $fileList = New-Object 'System.Collections.Generic.List[System.IO.FileInfo]'
  103.         $copyList = New-Object 'System.Collections.Generic.List[System.IO.FileInfo]'
  104.         $dirList = New-Object 'System.Collections.Generic.List[System.IO.DirectoryInfo]'
  105.         # [System.IO.FileAttributes]::Directory -eq 16
  106.  
  107.         foreach ($item in $gotcha)
  108.         {
  109.                 if (($item.Attributes -band 16) -eq 16)
  110.                         { $dirList.Add($item) }
  111.                 else
  112.                         { $fileList.Add($item) }
  113.         }
  114.  
  115.         $ref = Get-Comparable $fileList
  116.  
  117.         $syncDir = [System.IO.Directory]::CreateDirectory($Synchronized)
  118.         if ($syncDir -eq $null) { return $false }
  119.  
  120.         $syncFileList = Get-ChildItem -LiteralPath $syncDir.FullName -File
  121.         $sync = Get-Comparable $syncFileList
  122.         if ($sync -eq $null -or $ref -eq $null)
  123.         {
  124.                 $copyList = $fileList
  125.         }
  126.         else
  127.         {
  128.                 $compasion = Compare-Object -ReferenceObject $ref -DifferenceObject $sync
  129.                 foreach ($item in $compasion)
  130.                 {
  131.                         if ($item.SideIndicator -eq '<=')
  132.                         {
  133.                                 $copyList.Add($item.InputObject.Info)
  134.                         }
  135.                 }
  136.         }
  137.  
  138.         foreach ($item in $dirList)
  139.         {
  140.                 Start-FolderSync -Reference $item.FullName -Synchronized $($syncDir.FullName + '\' + $item.Name)
  141.         }
  142.        
  143.         foreach ($item in $copyList)
  144.         {
  145.                 Copy-Item -Path $item.FullName -Destination $syncDir.FullName -Verbose
  146.         }
  147. }

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me