private long GetSize(DirectoryInfo source) { var sourceInfos = source.GetFileSystemInfos(); var fileSystemInfoComparer = new FileSystemInfoComparer(); var sourceFiles = sourceInfos.Distinct(fileSystemInfoComparer) .GroupBy(f => f.FullName, StringComparer.InvariantCultureIgnoreCase) .Select(f => f.First()).OfType <FileInfo>(); var sourceDirs = sourceInfos.Distinct(fileSystemInfoComparer) .GroupBy(f => f.FullName, StringComparer.InvariantCultureIgnoreCase) .Select(f => f.First()).OfType <DirectoryInfo>().ToArray(); long size = 0; foreach (var file in sourceFiles) { if (_cancelRequested) { return(size); } size += file.Length; } foreach (var sourceDir in sourceDirs) { if (_cancelRequested) { return(size); } size += GetSize(sourceDir); } return(size); }
private void CopyDirectory(DirectoryInfo source, DirectoryInfo target, out bool cancelled) { if (_cancelRequested) { cancelled = true; return; } var fileSystemInfoComparer = new FileSystemInfoComparer(); var sourceFiles = source.GetFileSystemInfos().Distinct(fileSystemInfoComparer).GroupBy(f => f.Name, StringComparer.InvariantCultureIgnoreCase).Select(f => new { f.Key, Files = f.ToArray() }) .OrderByDescending(s => s.Files.Length).ThenBy(s => s.Files.First() is DirectoryInfo ? 0 : 1).ToArray(); if (!target.Exists) { target.Create(); } foreach (var sf in sourceFiles) { if (sf.Files.Length > 1) { Console.WriteLine("Duplicate file name: {0}: ", string.Join(", ", sf.Files.Select(s => s.FullName))); } var sourceFile = sf.Files.First(); if (_cancelRequested) { cancelled = true; return; } var directory = sourceFile as DirectoryInfo; var file = sourceFile as FileInfo; bool wasCancelled; if (directory != null) { CopyDirectory(directory, new DirectoryInfo(Path.Combine(target.FullName, directory.Name)), out wasCancelled); } if (file == null) { continue; } var outputFile = Path.Combine(target.FullName, file.Name); CopyIncrementally(file, outputFile, bytesRead => { _totalBytesCopied += bytesRead; var runningTime = _startTime.HasValue ? (DateTime.UtcNow - _startTime.Value) : default(TimeSpan?); lock (this) { Console.SetCursorPosition(0, Console.CursorTop); var total = _totalSize.HasValue && !string.IsNullOrWhiteSpace(_totalSizeString) ? string.Format("{0}/{1} ({2}%)", HumanReadableSize(_totalBytesCopied), _totalSizeString, (_totalBytesCopied * 100) / _totalSize.Value) : HumanReadableSize(_totalBytesCopied); var message = runningTime.HasValue ? string.Format("{0} copied ({1}/sec.)", total, HumanReadableSize(_totalBytesCopied / runningTime.Value.TotalSeconds)) : string.Format("{0} copied.", total); if (message.Length > Console.WindowWidth - 1) { message = message.Substring(Console.WindowWidth - 1); } var newMessageLength = message.Length; var blanksNeeded = Console.WindowWidth - newMessageLength - 1; var chars = new string(new char[blanksNeeded].Select(c => ' ').ToArray()); message = string.Format("{0}{1}", message, chars); Console.Write(message); } return(_cancelRequested); }); } cancelled = false; }