using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; namespace Aurora.Utils { public class FileSystemUtils { public FileSystemUtils() { } /// <summary> /// Asynchronousely recursively traverse a directory path. /// </summary> /// <param name="path">The path to the directory to traverse</param> /// <param name="extensions">Comma separated list of file extensions to accept</param> public static List<FileInfo> TraverseFoldersAsync(string path, string extensions) { string[] extensionList = extensions.Split(','); ConcurrentBag<Task> tasks = new ConcurrentBag<Task>(); List<FileInfo> outFiles = new List<FileInfo>(); DirectoryInfo directoryInfo = new DirectoryInfo(path); tasks.Add(Task.Run(() => Traverse(directoryInfo, tasks, outFiles, extensionList))); Task waitingTask; while (tasks.TryTake(out waitingTask)) { waitingTask.Wait(); } return outFiles; } /// <summary> /// Recursive method to capture children of a directory. /// </summary> /// <param name="dir">The directory to traverse</param> /// <param name="tasks">The list of currently running tasks</param> private static void Traverse(DirectoryInfo dir, ConcurrentBag<Task> tasks, List<FileInfo> outFiles, string[] extensions) { try { DirectoryInfo[] directoryInfos = dir.GetDirectories(); //Enque children foreach (DirectoryInfo childInfo in directoryInfos) { tasks.Add(Task.Run(() => Traverse(childInfo, tasks, outFiles, extensions))); } //Collect files foreach (FileInfo fileInfo in dir.GetFiles()) { if (extensions.Any(e => e == fileInfo.Extension)) { //Don't know if this lock is necessary lock (outFiles) { outFiles.Add(fileInfo); } } } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"{ex.GetType()} {ex.Message}\n{ex.StackTrace}"); ex = ex.InnerException; } } } }