/// <summary> /// ディレクトリの同期を行う。 /// </summary> public static void Run(string sourceDirectoryPath, string destDirectoryPath, bool deletable, Func <string, bool> isIgnoreFilePath) { var now = DateTime.Now; var baseBackupDirectoryPath = Path.Combine(destDirectoryPath, ".backup", $"{now.ToString("yyyy-MM-dd_HH-mm-ss")}"); var hashSet = new HashSet <string>(); foreach (var sourceFilePath in Directory.GetFiles(sourceDirectoryPath, "*", SearchOption.AllDirectories)) { string relativePath = sourceFilePath.Remove(0, sourceDirectoryPath.Length); string destFilePath = Path.Combine(destDirectoryPath, relativePath.Trim('\\')); if (isIgnoreFilePath(relativePath)) { continue; } // コピー対象ファイルとしてマーク。 hashSet.Add(destFilePath); var sourceLastWriteTime = new FileInfo(sourceFilePath).LastWriteTimeUtc; sourceLastWriteTime = sourceLastWriteTime.AddTicks(-(sourceLastWriteTime.Ticks % TimeSpan.TicksPerSecond)); var destLastWriteTime = new FileInfo(destFilePath).LastWriteTimeUtc; destLastWriteTime = destLastWriteTime.AddTicks(-(destLastWriteTime.Ticks % TimeSpan.TicksPerSecond)); // コピー先にファイルが存在し、最終書き込み日時が大きい場合、コピーしない。 if (File.Exists(destFilePath) && destLastWriteTime >= (sourceLastWriteTime)) { continue; } // コピー先ディレクトリを作成する。 { string parentDirectoryPath = Path.GetDirectoryName(destFilePath); if (!Directory.Exists(parentDirectoryPath)) { Directory.CreateDirectory(parentDirectoryPath); } } try { // コピー先にファイルが存在する場合、バックアップディレクトリへ移動する。 if (File.Exists(destFilePath)) { var backupFilePath = Path.Combine(baseBackupDirectoryPath, relativePath.Trim('\\')); var backupParentDirectoryPath = Path.GetDirectoryName(backupFilePath); if (!Directory.Exists(backupParentDirectoryPath)) { Directory.CreateDirectory(backupParentDirectoryPath); } File.Move(destFilePath, backupFilePath); } File.Copy(sourceFilePath, destFilePath, true); Console.WriteLine($"{now.ToString("yyyy/MM/dd HH:mm:ss")} Copy: {sourceFilePath} -> {destFilePath}"); } catch (Exception) { } } // 削除しない。 if (!deletable) { return; } // コピー対象でないファイルがコピー先フォルダに存在する場合、コピー先から該当ファイルを削除する。 foreach (var destFilePath in Directory.GetFiles(destDirectoryPath, "*", SearchOption.AllDirectories)) { if (hashSet.Contains(destFilePath)) { continue; } string relativePath = destFilePath.Remove(0, destDirectoryPath.Length); if (isIgnoreFilePath(relativePath)) { continue; } try { // コピー先にファイルが存在する場合、バックアップディレクトリへ移動する。 if (File.Exists(destFilePath)) { var backupFilePath = Path.Combine(baseBackupDirectoryPath, relativePath.Trim('\\')); var backupParentDirectoryPath = Path.GetDirectoryName(backupFilePath); if (!Directory.Exists(backupParentDirectoryPath)) { Directory.CreateDirectory(backupParentDirectoryPath); } File.Move(destFilePath, backupFilePath); } Console.WriteLine($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} Delete: {destFilePath}"); } catch (Exception) { } } // コピー先フォルダ内の空のフォルダを削除する。 foreach (var path in Directory.GetDirectories(destDirectoryPath, "*", SearchOption.AllDirectories).Reverse()) { try { Directory.Delete(path, false); } catch (Exception) { } } }