public int Run(RunArgs ra) { ra.State.DestinationDir = ra.RootDir.FullName; Utils.ReadString("destination dir: ", ref ra.State.DestinationDir); Utils.ReadInt("number length with zero padding (6) : ", ref ra.State.PadZeroes); Utils.ReadString("search pattern (*.*): ", ref ra.State.SearchPattern); var useexisting = false; if (ra.State.Files != null && ra.State.Files.Length > 0) { string.Format( "There are {0} files from a previous subprogram run. {1}Frst of the old files: {2} ", ra.State.Files.Length, Environment.NewLine, ra.State.Files[0]).PrintLine(); useexisting = Utils.ReadWord("Use them? (y/*) ", "y"); } if (!useexisting) { ra.State.Files = ra.RootDir.GetFiles(ra.State.SearchPattern, SearchOption.TopDirectoryOnly); } else if (Utils.ReadWord(string.Format("Change the root dir ({0}) ? (y/*)", ra.RootDir.FullName), "y")) { var newroot = string.Empty; Utils.ReadString("Enter new root dir: ", ref newroot, true); ra.ChangeRoot(newroot); } string.Format("There are {0} matches.", ra.State.Files.Length).PrintLine(); ra.Trace = Utils.ReadWord("Trace first? (y/*): ", "y"); var FI = new List <FileInfo>(); if (ra.Trace) { PadFiles(ra, FI); } if (Utils.ReadWord("Pad all? (y/*): ", "y")) { PadFiles(ra, FI, true); ra.State.Files = FI.ToArray(); $"Done - {ra.State.Files.Length} files renamed.".PrintLine(); } else { "Aborting pad.".PrintLine(); } return(0); }
public int Run(RunArgs ra) { Utils.ReadString("the path of the text file with the new file names: ", ref ra.State.FileNamesFilePath, true); Utils.ReadString("destination dir: ", ref ra.State.DestinationDir, true); Utils.ReadString("search pattern (*.*): ", ref ra.State.SearchPattern); Utils.ReadString("prefix: ", ref ra.State.Prefix); Utils.ReadString("name from file prefix: ", ref ra.State.NameFromFilePrefix); Utils.ReadInt("counter (0) : ", ref ra.State.NameCounter); Utils.ReadInt("counter step (1) : ", ref ra.State.NameCounterStep); Utils.ReadInt("number length with zero padding (6) : ", ref ra.State.PadZeroes); "sort options: no-0, asc name-1, desc name-2, randomize-3, asc createdate-4, desc createdate-5. ".PrintLine(); int sort = 0; Utils.ReadIntIn("sort first (no) : ", ref sort, new int[] { 0, 1, 2, 3, 4, 5 }); ra.State.Sort = (SortType)sort; var useexisting = false; if (ra.State.Files != null && ra.State.Files.Length > 0) { string.Format( "There are {0} files from a previous subprogram run. {1}The first of the old files: {2} ", ra.State.Files.Length, Environment.NewLine, ra.State.Files[0]).PrintLine(); useexisting = Utils.ReadWord("Use them? (y/*) ", "y"); } if (!useexisting) { ra.State.Files = ra.RootDir.GetFiles(ra.State.SearchPattern, SearchOption.TopDirectoryOnly); } else if (Utils.ReadWord(string.Format("Change the root dir ({0}) ? (y/*)", ra.RootDir.FullName), "y")) { var newroot = string.Empty; Utils.ReadString("Enter new root dir: ", ref newroot, true); ra.ChangeRoot(newroot); } ra.State.SortFiles(ra.State.Sort); string.Format("There are {0} matches.", ra.State.Files.Length).PrintLine(); ra.Trace = Utils.ReadWord("Trace first? (y/*): ", "y"); var newNames = File.ReadAllLines(ra.State.FileNamesFilePath); if (newNames.Length < ra.State.Files.Length) { var msg = string.Format( "The new names length is {0} and the files to be renamed are {1}. Abort? (y/*)", newNames.Length, ra.State.Files.Length); if (Utils.ReadWord(msg, "y")) { return(-1); } } string.Format("Files - {0}, Names - {1}", newNames.Length, ra.State.Files.Length).PrintLine(ConsoleColor.Yellow); if (ra.Trace) { var tcounter = ra.State.NameCounter; var i = 0; foreach (var f in ra.State.Files) { if (f.FullName == ra.Me) { continue; } tcounter += ra.State.NameCounterStep; var padded = PadNumbers.PadZeroes(tcounter.ToString(), ra.State.PadZeroes); var newname = string.Format("{0}{1}{2}{3}{4}", ra.State.Prefix, padded, ra.State.NameFromFilePrefix, newNames[i], f.Extension); var newpath = Path.Combine(ra.State.DestinationDir, newname); string.Format(f.Name + " --> " + newpath).PrintLine(ConsoleColor.Yellow); i++; } } if (Utils.ReadWord("Rename all? (y/*): ", "y")) { var FI = new List <FileInfo>(); var i = 0; foreach (var f in ra.State.Files) { if (f.FullName == ra.Me) { continue; } ra.State.IncrementCounter(); var padded = PadNumbers.PadZeroes(ra.State.NameCounter.ToString(), ra.State.PadZeroes); var newname = string.Format("{0}{1}{2}{3}{4}", ra.State.Prefix, padded, ra.State.NameFromFilePrefix, newNames[i], f.Extension); var newpath = Path.Combine(ra.State.DestinationDir, newname); File.Move(f.FullName, newpath); FI.Add(new FileInfo(newpath)); i++; } ra.State.Files = FI.ToArray(); $"Done - {ra.State.Files.Length} files renamed.".PrintLine(); } else { "Aborting rename.".PrintLine(); } return(0); }
public int Run(RunArgs ra) { bool interactive = !ra.InArgs.ContainsKey("-ni"); var copy = true; var recursive = SearchOption.TopDirectoryOnly; var mirrorDir = false; var ignoreST = 0; var ignoreBT = int.MaxValue / 1000; var regx = string.Empty; if (interactive) { var src = string.Empty; Utils.ReadString("Source dir: ", ref src); if (!string.IsNullOrEmpty(src)) { ra.RootDir = new DirectoryInfo(src); } Utils.ReadString("Destination dir: ", ref ra.State.DestinationDir, true); Utils.ReadString("Search pattern (*.*): ", ref ra.State.SearchPattern); Utils.ReadInt("Ignore files smaller than (in KB): ", ref ignoreST); Utils.ReadInt("Ignore files bigger than (in KB): ", ref ignoreBT); Utils.ReadString("Path matching regex: ", ref regx); Utils.ReadString("Taken files prefix: ", ref ra.State.Prefix); if (Utils.ReadWord("Recursive? (y/*): ", "y")) { recursive = SearchOption.AllDirectories; } if (recursive == SearchOption.AllDirectories && Utils.ReadWord("Mirror dir tree? (y/*): ", "y")) { mirrorDir = true; } copy = !Utils.ReadWord("Move? (y/*): ", "y"); } else { if (ra.InArgs.ContainsKey("-src")) { ra.RootDir = new DirectoryInfo(ra.InArgs.GetFirstValue("-src")); } ra.State.DestinationDir = ra.InArgs.GetFirstValue("-dest"); if (ra.InArgs.ContainsKey("-sp")) { ra.State.SearchPattern = ra.InArgs.GetFirstValue("-sp"); } if (ra.InArgs.ContainsKey("-prf")) { ra.State.Prefix = ra.InArgs.GetFirstValue("-prf"); } ra.State.Take = int.Parse(ra.InArgs.GetFirstValue("-take")); if (ra.InArgs.ContainsKey("-r")) { recursive = SearchOption.AllDirectories; if (ra.InArgs.ContainsKey("-mt")) { mirrorDir = true; } } if (ra.InArgs.ContainsKey("-ist")) { ignoreST = int.Parse(ra.InArgs.GetFirstValue("-ist")); } if (ra.InArgs.ContainsKey("-ibt")) { ignoreBT = int.Parse(ra.InArgs.GetFirstValue("-ibt")); } if (ra.InArgs.ContainsKey("-reg")) { regx = ra.InArgs.GetFirstValue("-reg"); } if (ra.InArgs.ContainsKey("-move")) { copy = false; } } if (ignoreST > ignoreBT || ignoreBT < 1 || ignoreST < 0) { throw new ArgumentException(); } ignoreST *= 1000; ignoreBT *= 1000; if (!Directory.Exists(ra.State.DestinationDir)) { Directory.CreateDirectory(ra.State.DestinationDir); } ra.State.Files = ra.RootDir.GetFiles(ra.State.SearchPattern, recursive) .Where(x => x.Length > ignoreST && x.Length < ignoreBT && (string.IsNullOrEmpty(regx) || Regex.IsMatch(x.FullName, regx))) .Select(x => x).ToArray(); if (interactive) { Utils.ReadInt(string.Format("There are {0} matches. take (0): ", ra.State.Files.Length), ref ra.State.Take); } ra.Trace = interactive ? Utils.ReadWord("Trace first? (y/*): ", "y") : true; List <int> R = Utils.Randomize(ra.State.Files.Length); if (ra.State.Files.Length < ra.State.Take) { ra.State.Take = ra.State.Files.Length; } if (ra.Trace) { for (var i = 0; i < ra.State.Take; i++) { var j = R[i]; var f = ra.State.Files[j]; if (f.FullName == ra.Me) { continue; } var newname = mirrorDir ? Path.Combine( f.Directory.FullName.Replace( ra.RootDir.FullName, string.Empty), ra.State.Prefix + f.Name) .TrimStart(Path.DirectorySeparatorChar) : string.Format("{0}{1}", ra.State.Prefix, f.Name); string.Format("{0} -->{1}{2}{1}", f.FullName, Environment.NewLine, Path.Combine(ra.State.DestinationDir, newname)) .PrintLine(ConsoleColor.Yellow); } } if (!interactive || (interactive && Utils.ReadWord("Take? (y/*): ", "y"))) { var FI = new List <FileInfo>(); for (var i = 0; i < ra.State.Take; i++) { var j = R[i]; var f = ra.State.Files[j]; var newname = mirrorDir ? Path.Combine( f.Directory.FullName.Replace( ra.RootDir.FullName, string.Empty), ra.State.Prefix + f.Name) .TrimStart(Path.DirectorySeparatorChar) : string.Format("{0}{1}", ra.State.Prefix, f.Name); var newpath = Path.Combine(ra.State.DestinationDir, newname); if (!Directory.Exists(newpath)) { Directory.CreateDirectory(Path.GetDirectoryName(newpath)); } if (copy) { File.Copy(f.FullName, newpath); } else { File.Move(f.FullName, newpath); } FI.Add(new FileInfo(newpath)); } ra.State.Files = FI.ToArray(); $"Done - {ra.State.Take} files copied.".PrintLine(); } else { "Aborting take.".PrintLine(); } return(0); }
public int Run(RunArgs ra) { bool interactive = !ra.InArgs.ContainsKey("-ni"); var srcDirs = new List <DirectoryInfo>(); var srcs = string.Empty; var skipLessThanSize = 1; var skipMoreThanSize = -1; var ignExt = string.Empty; var iExt = new List <string>(); var compHash = false; var recursive = false; var inParallel = 1; var delete = false; var saveas = string.Empty; var saveType = string.Empty; ra.State.SearchPattern = "*.*"; if (interactive) { Utils.ReadString("Enter folders to search into, separated by semicolon: ", ref srcs, true); Utils.ReadString("Search pattern (*.*): ", ref ra.State.SearchPattern); recursive = !Utils.ReadWord("Recursive search? (n/*): ", "n"); Utils.ReadInt($"Skip if size < 1Kb: ", ref skipLessThanSize, false); Utils.ReadInt($"Skip if size > #Kb: ", ref skipMoreThanSize, false); Utils.ReadString("Skip extensions (.xyz): ", ref ignExt, false); compHash = Utils.ReadWord("Compare file names (default) or MD5 hashes? (h/*): ", "h"); } else { if (ra.InArgs.ContainsKey("-dirs")) { srcs = ra.InArgs.GetFirstValue("-dirs"); } else { throw new ArgumentNullException("-dirs"); } if (ra.InArgs.ContainsKey("-sp")) { ra.State.SearchPattern = ra.InArgs.GetFirstValue("-sp"); } if (ra.InArgs.ContainsKey("-rec")) { recursive = true; } if (ra.InArgs.ContainsKey("-j")) { inParallel = int.Parse(ra.InArgs.GetFirstValue("-j")); } if (ra.InArgs.ContainsKey("-hash")) { compHash = true; } if (ra.InArgs.ContainsKey("-del")) { delete = true; } if (ra.InArgs.ContainsKey("-save")) { saveas = ra.InArgs.GetFirstValue("-save"); saveType = Path.GetExtension(saveas).Replace(".", ""); } } if (!string.IsNullOrEmpty(ignExt)) { foreach (var ext in ignExt.Split(';')) { iExt.Add(ext.Trim()); } } var useStreamReduction = false; var take = 4000; var skip = 10000; if (compHash && interactive) { Utils.ReadInt($"Concurrent readers (1-{Environment.ProcessorCount}): ", ref inParallel); "By default the hash is computed over the whole file.".PrintLine(); "You can use skip and take parameters to read a portion of the file.".PrintLine(); useStreamReduction = Utils.ReadWord("Do you want to use skip/take? (y/*): ", "y"); if (useStreamReduction) { "The reader always starts with a TAKE (position 0).".PrintLine(); Utils.ReadInt($"Take bytes ({take}): ", ref take, false); Utils.ReadInt($"Skip bytes ({skip}): ", ref skip, false); if (skip < 0 || take < 0) { throw new ArgumentOutOfRangeException("Negative skip or take value."); } } } if (inParallel < 1 || inParallel > Environment.ProcessorCount) { throw new ArgumentOutOfRangeException("inParallel", $"The concurrent readers should be between 0 and {Environment.ProcessorCount}"); } foreach (var p in srcs.Split(';')) { if (Directory.Exists(p)) { srcDirs.Add(new DirectoryInfo(p)); } else { throw new DirectoryNotFoundException(p); // will throw if the path is invalid } } var All = new List <List <FileInfo> >(); var searchOpt = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; // Some subdirectories may be restricted and the GetFiles will throw with AccesDenied // so loop the individual folders separately. foreach (var d in srcDirs) { try { foreach (var sd in d.EnumerateDirectories("*", searchOpt).Union(new DirectoryInfo[] { d })) { try { var L = new List <FileInfo>(); foreach (var file in sd.EnumerateFiles(ra.State.SearchPattern, SearchOption.TopDirectoryOnly)) { if (iExt.Count > 0 && iExt.Contains(file.Extension)) { continue; } if (skipLessThanSize > 0 && file.Length < skipLessThanSize) { continue; } if (skipMoreThanSize > 0 && file.Length > skipMoreThanSize) { continue; } L.Add(file); } All.Add(L); } catch (Exception ex) { ex.Message.PrintLine(ConsoleColor.Red); } } } catch (Exception ex) { ex.Message.PrintLine(ConsoleColor.Red); } } var dict = new Dictionary <string, List <FileInfo> >(); var sb = new StringBuilder(); var totalFiles = 0; var totalFilesChecked = 0; // In all cases the length will be the same foreach (var src in All) { foreach (var fi in src) { var key = $"{fi.Length}"; if (!dict.ContainsKey(key)) { dict.Add(key, new List <FileInfo>()); } else { totalFiles++; } totalFilesChecked++; dict[key].Add(fi); } } totalFiles += totalFiles; // Either compare the names or the data hashes var hashDict = new Dictionary <string, List <FileInfo> >(); var totalDuplicates = 0; var counter = 0; var hashDictSpin = new SpinLock(); $"{Environment.NewLine}Total files checked: {totalFilesChecked}".PrintLine(); Console.CursorVisible = false; var cursorTop = Console.CursorTop; foreach (var kv in dict) { if (kv.Value.Count > 1) { if (compHash) { Console.SetCursorPosition(0, cursorTop); Parallel.For(0, kv.Value.Count, new ParallelOptions() { MaxDegreeOfParallelism = inParallel }, (i) => { try { Stream stream = File.OpenRead(kv.Value[i].FullName); if (useStreamReduction) { stream = new StreamReductor(stream, skip, take); } using (var md5 = MD5.Create()) using (stream) { $"{++counter}/{totalFiles} [{kv.Value[i].Length / 1000}]Kb file{i} = {kv.Value[i].FullName}".PrintLine(ConsoleColor.Yellow); var h = md5.ComputeHash(stream); var key = BitConverter.ToString(h); var acq = false; hashDictSpin.Enter(ref acq); if (acq) { if (!hashDict.ContainsKey(key)) { hashDict.Add(key, new List <FileInfo>()); } else { totalDuplicates++; } hashDict[key].Add(kv.Value[i]); hashDictSpin.Exit(); } } } catch (Exception ex) { ex.Message.PrintSysError(); return; } }); var cursorTopNow = Console.CursorTop; for (int top = cursorTop; top < cursorTopNow; top++) { for (int left = 0; left < Console.WindowWidth; left++) { Console.SetCursorPosition(left, top); " ".Print(); } } } else { foreach (var f in kv.Value) { var key = f.Name.ToLowerInvariant(); if (!hashDict.ContainsKey(key)) { hashDict.Add(key, new List <FileInfo>()); } else { totalDuplicates++; } hashDict[key].Add(f); $"Comparing {++counter}/{totalFiles}".Print(ConsoleColor.Yellow); Console.SetCursorPosition(0, Console.CursorTop); } } } } Console.SetCursorPosition(0, cursorTop); Console.CursorVisible = true; sb.AppendLine("Files with the same length and name/hash are grouped together."); sb.AppendLine(); foreach (var kv in hashDict) { if (kv.Value.Count > 1) { var size = kv.Value[0].Length / 1000; string lbl = size < 1 ? lbl = $"{kv.Value[0].Length}b" : $"{size}Kb"; sb.AppendLine($"[{kv.Key}] {lbl}"); foreach (var p in kv.Value) { sb.AppendLine(p.FullName); } sb.AppendLine(); } } $"There are {totalDuplicates} files with clones.".PrintLine(); if (totalDuplicates > 0) { ra.Trace = interactive && Utils.ReadWord("Trace? (y/*): ", "y"); if (ra.Trace) { sb.ToString().PrintLine(ConsoleColor.Yellow); } // In case of -ni var opt = saveType; if (delete || (interactive && Utils.PickOption("Save results? (fdelete, xml, json, txt/*): ", ref opt, false, "fdelete", "xml", "json", "txt"))) { var fn = string.Empty; var data = string.Empty; if (interactive) { Utils.ReadString("Result file path: ", ref fn, true); } else { fn = saveas; } if (opt == "fdelete" || delete) { var toDel = new StringBuilder(); foreach (var kv in hashDict) { if (kv.Value.Count > 1) { foreach (var f in kv.Value.Select(x => x.FullName).Skip(1)) { toDel.AppendLine(f); if (delete && File.Exists(f)) { File.Delete(f); } } } } data = toDel.ToString(); } if (opt == "txt") { data = sb.ToString(); } else { var L = new List <Duplicate>(); foreach (var kv in hashDict) { if (kv.Value.Count > 1) { L.Add(new Duplicate(kv.Key, kv.Value[0].Length, kv.Value.Select(x => x.FullName).ToArray())); } } if (opt == "json") { data = L.ToJson(); } else { data = L.ToXml(); } } if (!string.IsNullOrEmpty(fn)) { File.WriteAllText(fn, data); } } } return(0); }
public int Run(RunArgs ra) { bool interactive = !ra.InArgs.ContainsKey("-ni"); int sort = 4; string src = null; ra.Trace = false; ra.State.NameCounter = int.MinValue; if (interactive) { Utils.ReadString("Source dir (current): ", ref src); if (!string.IsNullOrEmpty(src)) { ra.ChangeRoot(src); } Utils.ReadString("Destination dir: ", ref ra.State.DestinationDir, true); Utils.ReadString("Search pattern (*.*): ", ref ra.State.SearchPattern); Utils.ReadString("Prefix: ", ref ra.State.Prefix); Utils.ReadInt("Counter start value (default is prefix only): ", ref ra.State.NameCounter); if (ra.State.NameCounter > int.MinValue) { Utils.ReadInt("Counter step (1): ", ref ra.State.NameCounterStep); Utils.ReadInt("Number length with zero padding (6): ", ref ra.State.PadZeroes); "Sort options: no-0, asc name-1, desc name-2, randomize-3, asc createdate-4, desc createdate-5. ".PrintLine(); Utils.ReadIntIn("Option (4): ", ref sort, new int[] { 0, 1, 2, 3, 4, 5 }); } } else { ra.ChangeRoot(ra.InArgs.GetFirstValue("-src")); ra.State.DestinationDir = ra.InArgs.GetFirstValue("-dest"); if (ra.InArgs.ContainsKey("-sp")) { ra.State.SearchPattern = ra.InArgs.GetFirstValue("-sp"); } if (ra.InArgs.ContainsKey("-prf")) { ra.State.Prefix = ra.InArgs.GetFirstValue("-prf"); } if (ra.InArgs.ContainsKey("-ic")) { ra.State.NameCounter = int.Parse(ra.InArgs.GetFirstValue("-ic")); } if (ra.InArgs.ContainsKey("-step")) { ra.State.NameCounterStep = int.Parse(ra.InArgs.GetFirstValue("-step")); } if (ra.InArgs.ContainsKey("-zpad")) { ra.State.PadZeroes = int.Parse(ra.InArgs.GetFirstValue("-zpad")); } if (ra.InArgs.ContainsKey("-sort")) { ra.State.PadZeroes = int.Parse(ra.InArgs.GetFirstValue("-sort")); } } ra.State.Sort = (SortType)sort; ra.State.Files = ra.RootDir.GetFiles(ra.State.SearchPattern, SearchOption.TopDirectoryOnly); ra.State.SortFiles(ra.State.Sort); string.Format("There are {0} matches.", ra.State.Files.Length).PrintLine(); if (interactive) { ra.Trace = Utils.ReadWord("Trace first? (y/*): ", "y"); } string padded, newpath, newname; if (ra.Trace) { var tcounter = ra.State.NameCounter; foreach (var f in ra.State.Files) { if (f.FullName == ra.Me) { continue; } if (ra.State.NameCounter > int.MinValue) { tcounter += ra.State.NameCounterStep; padded = PadNumbers.PadZeroes(tcounter.ToString(), ra.State.PadZeroes); newname = string.Format("{0}{1}{2}", ra.State.Prefix, padded, f.Extension); } else { newname = ra.State.Prefix + f.Name; } newpath = Path.Combine(ra.State.DestinationDir, newname); string.Format(f.Name + " --> " + newpath).PrintLine(ConsoleColor.Yellow); } } if (!interactive || Utils.ReadWord("Rename all? (y/*): ", "y")) { var FI = new List <FileInfo>(); foreach (var f in ra.State.Files) { if (f.FullName == ra.Me) { continue; } if (ra.State.NameCounter > int.MinValue) { ra.State.IncrementCounter(); padded = PadNumbers.PadZeroes(ra.State.NameCounter.ToString(), ra.State.PadZeroes); newname = string.Format("{0}{1}{2}", ra.State.Prefix, padded, f.Extension); } else { newname = ra.State.Prefix + f.Name; } newpath = Path.Combine(ra.State.DestinationDir, newname); File.Move(f.FullName, newpath); FI.Add(new FileInfo(newpath)); } ra.State.Files = FI.ToArray(); $"Done - {ra.State.Files.Length} files renamed.".PrintLine(); } else { "Aborting move.".PrintLine(); } return(0); }
public int Run(RunArgs ra) { bool interactive = !ra.InArgs.ContainsKey("-ni"); var baseUrl = string.Empty; var linksFile = string.Empty; var reqPerSec = 5.0; var fromIdx = 0; var toIdx = -1; var url = string.Empty; ra.State.DestinationDir = ra.RootDir.FullName; if (interactive) { Utils.ReadString("destination dir: ", ref ra.State.DestinationDir); Utils.ReadString("url: ", ref url); if (string.IsNullOrWhiteSpace(url)) { Utils.ReadString("base url: ", ref baseUrl); Utils.ReadString("links file: ", ref linksFile, true); Utils.ReadDouble("req/sec: ", ref reqPerSec); Utils.ReadInt("from row: ", ref fromIdx); Utils.ReadInt("to row: ", ref toIdx); } } else { if (ra.InArgs.ContainsKey("-f")) { linksFile = ra.InArgs.GetFirstValue("-f"); } if (ra.InArgs.ContainsKey("-base")) { baseUrl = ra.InArgs.GetFirstValue("-base"); } if (ra.InArgs.ContainsKey("-url")) { url = ra.InArgs.GetFirstValue("-url"); } if (ra.InArgs.ContainsKey("-dest")) { ra.State.DestinationDir = ra.InArgs.GetFirstValue("-dest"); } if (ra.InArgs.ContainsKey("-rps")) { reqPerSec = double.Parse(ra.InArgs.GetFirstValue("-rps")); } if (ra.InArgs.ContainsKey("-from")) { fromIdx = int.Parse(ra.InArgs.GetFirstValue("-from")); } if (ra.InArgs.ContainsKey("-to")) { toIdx = int.Parse(ra.InArgs.GetFirstValue("-to")); } } string[] links = null; if (!string.IsNullOrWhiteSpace(url)) { links = new string[] { url } } ; else { links = File.ReadAllLines(linksFile); } if (toIdx < 0) { toIdx = links.Length; } if (fromIdx > 0 && fromIdx > links.Length) { throw new ArgumentOutOfRangeException("from"); } if (toIdx > 0 && (toIdx > links.Length || toIdx <= fromIdx)) { throw new ArgumentOutOfRangeException("to"); } links = links.Skip(fromIdx).Take(toIdx - fromIdx).ToArray(); var LINKS_COUNT = links.Length; var c = 0; var counter = new CountdownEvent(LINKS_COUNT); var startTime = DateTime.Now; if (links != null && LINKS_COUNT > 0) { for (int i = 0; i < LINKS_COUNT; i++) { var rps = i / DateTime.Now.Subtract(startTime).TotalSeconds; while (rps > reqPerSec) { Thread.Sleep(100); rps = i / DateTime.Now.Subtract(startTime).TotalSeconds; } new Task(async(o) => { var idx = (int)o; Uri uri = null; var fn = string.Empty; try { using (var webClient = new HttpClient()) { var link = links[idx]; if (!string.IsNullOrEmpty(baseUrl)) { uri = new Uri(string.Format("{0}/{1}", baseUrl, link)); fn = Path.Combine(ra.State.DestinationDir, link); } else { uri = new Uri(link); fn = Path.Combine(ra.State.DestinationDir, uri.Segments[uri.Segments.Length - 1]); } var bytes = await webClient.GetByteArrayAsync(uri); using (var fs = new FileStream( fn, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, bytes.Length, true)) await fs.WriteAsync(bytes, 0, bytes.Length); string.Format("{0, 6}/{1}| {2, 6}|K {3}", Interlocked.Increment(ref c), LINKS_COUNT, bytes.Length / 1000, fn).PrintInfo(true); } } catch (Exception ex) { $"@ link {links[idx]}".PrintSysError(true); ex.Message.PrintSysError(true); } finally { counter.Signal(); } }, i).Start(); } } counter.Wait(); var dur = DateTime.Now.Subtract(startTime); $"{Environment.NewLine}Done [{dur.Hours}h {dur.Minutes}m {dur.Seconds}s].".PrintInfo(true); return(0); }