private void CopySourceToDestination(CopyItem item, OrganizeSummary summary) { string destinationDirectory = Path.GetDirectoryName(item.destinationPath); if (!Directory.Exists(destinationDirectory)) { try { Directory.CreateDirectory(destinationDirectory); } catch (Exception ex) { if (ExceptionHandling == ExceptionHandling.Throw) { throw new MediaOrganizerException($"Failed to create directory: {destinationDirectory}", ex); } Trace.WriteLine($"[{nameof(MediaOrganizer)}] Ignored exception: {ex.Message}"); return; } } summary.sources.Add(item.sourcePath); summary.destinations.Add(item.destinationPath); bool overwrite = false; string targetDestinationPath = item.destinationPath; // Note: path may be altered later on to resolve conflicts bool fileExists = File.Exists(targetDestinationPath); switch (CopyMode) { case CopyMode.OverwriteExisting: overwrite = true; if (fileExists) { summary.overwritten[item.sourcePath] = targetDestinationPath; Trace.WriteLine($"[{nameof(MediaOrganizer)}] Force overwrite file: {targetDestinationPath}"); } break; case CopyMode.KeepExisting: if (fileExists) { summary.skipped[item.sourcePath] = targetDestinationPath; Trace.WriteLine($"[{nameof(MediaOrganizer)}] Keep existing file: {targetDestinationPath}"); return; } break; case CopyMode.KeepUnique: FileInfo sourceInfo = item.sourceInfo; FileInfo destinationInfo = new FileInfo(targetDestinationPath); if (fileExists) { // Potentially slow, therefore previous optimizations if (sourceInfo.AreFilesIdentical(destinationInfo, FileComparator)) { summary.duplicates[item.sourcePath] = targetDestinationPath; Trace.WriteLine($"[{nameof(MediaOrganizer)}] Duplicate file ignored: {item.sourcePath} (duplicate of {targetDestinationPath})"); return; } } if (sourceInfo.FileExistsInDirectory(destinationInfo.Directory, FileComparator)) { summary.duplicates[item.sourcePath] = destinationInfo.Directory.FullName; Trace.WriteLine($"[{nameof(MediaOrganizer)}] Duplicate file ignored: {item.sourcePath} (exists in {destinationInfo.Directory})"); return; // Source file already exists in target directory } // Find next unused filename string originalDestinationPath = targetDestinationPath; int index = 1; while (fileExists) { targetDestinationPath = destinationInfo.SuffixFileName(index++); fileExists = File.Exists(targetDestinationPath); } if (targetDestinationPath != originalDestinationPath) { summary.renamed[originalDestinationPath] = targetDestinationPath; Trace.WriteLine($"[{nameof(MediaOrganizer)}] Renamed to prevent conflict: {targetDestinationPath} (original: {originalDestinationPath})"); } break; default: throw new NotImplementedException($"CopyMode: {CopyMode}"); } try { File.Copy(item.sourcePath, targetDestinationPath, overwrite); summary.modified.Add(targetDestinationPath); if (FileVerification != FileComparator.None) { if (!item.sourceInfo.AreFilesIdentical(new FileInfo(targetDestinationPath), FileVerification)) { throw new MediaOrganizerException("File verification failed. Source: {0}. Destination: {1}", item.sourcePath, targetDestinationPath); } } } catch (Exception ex) { if (ExceptionHandling == ExceptionHandling.Throw) { throw new MediaOrganizerException($"Failed to copy file. Mode: {CopyMode}. Overwrite: {overwrite}. Source: {item.sourcePath}. Destination: {targetDestinationPath}", ex); } Trace.WriteLine($"[{nameof(MediaOrganizer)}] Ignored exception: {ex.Message}"); } }