using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace RandomFileRunner.IO { public class SmartDirectory { public static List GetFiles(string path, string pattern, bool searchTopOnly) { List fileList = new List(); List directoryList = new List(); if (string.IsNullOrWhiteSpace(pattern)) pattern = "*"; directoryList.Add(path); while (true) { if (directoryList.Count <= 0) { break; } string directory = directoryList.First(); directoryList.RemoveAt(0); if (IsDirectoryAccessible(directory)) { IEnumerable searchDirList = new List(); try { searchDirList = Directory.EnumerateDirectories(directory, "*", SearchOption.TopDirectoryOnly); } catch (Exception) { continue; } if (!searchTopOnly) { foreach (string item in searchDirList) { if (!IsDirectoryAccessible(item)) { continue; } directoryList.Add(item); } } foreach (string item in Directory.EnumerateFiles(directory, "*", SearchOption.TopDirectoryOnly)) { if (!MatchFileSearchPattern(pattern, Path.GetFileName(item))) { continue; } if (!IsFileAccessible(item)) { continue; } fileList.Add(item); } } } return fileList; } public static void GetFiles(string path, string pattern, bool searchTopOnly, Func callback) { List directoryList = new List(); ulong searchCount = 0; if (string.IsNullOrWhiteSpace(pattern)) pattern = "*"; directoryList.Add(path); searchCount++; while (true) { if (directoryList.Count <= 0) { break; } string directory = directoryList.First(); directoryList.RemoveAt(0); callback(null, searchCount, directoryList.Count); if (IsDirectoryAccessible(directory)) { IEnumerable searchDirList = new List(); try { searchDirList = Directory.EnumerateDirectories(directory, "*", SearchOption.TopDirectoryOnly); } catch (Exception) { continue; } if (!searchTopOnly) { foreach (string item in searchDirList) { if (!IsDirectoryAccessible(item)) { continue; } directoryList.Add(item); searchCount++; callback(null, searchCount, directoryList.Count); } } foreach (string item in Directory.EnumerateFiles(directory, "*", SearchOption.TopDirectoryOnly)) { if (!MatchFileSearchPattern(pattern, Path.GetFileName(item))) { continue; } if (!IsFileAccessible(item)) { continue; } callback(item, searchCount, directoryList.Count); } } } } public static bool IsFileAccessible(string filename) { if (string.IsNullOrWhiteSpace(filename)) return false; if (!File.Exists(filename)) return false; try { FileInfo fi = new FileInfo(filename); fi.GetAccessControl(); } catch { return false; } return true; } public static bool IsDirectoryAccessible(string path) { if (string.IsNullOrWhiteSpace(path)) return false; if (!Directory.Exists(path)) return false; try { DirectoryInfo di = new DirectoryInfo(path); di.GetAccessControl(); } catch { return false; } return true; } public static bool MatchFileSearchPattern(string pattern, string subject) { if (string.IsNullOrWhiteSpace(pattern)) { return false; } Func matchPattern = (pattern, subject) => { string[] parts = pattern.Split('*'); if (parts.Length <= 1) { return subject.Equals(pattern, StringComparison.CurrentCultureIgnoreCase); } int pos = 0; for (int i = 0; i < parts.Length; i++) { if (i <= 0) { // first pos = subject.IndexOf(parts[i], pos, StringComparison.CurrentCultureIgnoreCase); if (pos != 0) { return false; } } else if (i >= (parts.Length - 1)) { // last if (!subject.EndsWith(parts[i], StringComparison.CurrentCultureIgnoreCase)) { return false; } } else { pos = subject.IndexOf(parts[i], pos, StringComparison.CurrentCultureIgnoreCase); if (pos < 0) { return false; } pos += parts[i].Length; } } return true; }; Func matchAllPattern = (pattern, subject) => { int wildcardCount = pattern.Count(x => x.Equals('*')); if (wildcardCount <= 0) { return subject.Equals(pattern, StringComparison.CurrentCultureIgnoreCase); } else if (wildcardCount == 1) { string newWildcardPattern = pattern.Replace("*", ""); if (pattern.StartsWith("*")) { return subject.EndsWith(newWildcardPattern, StringComparison.CurrentCultureIgnoreCase); } else if (pattern.EndsWith("*")) { return subject.StartsWith(newWildcardPattern, StringComparison.CurrentCultureIgnoreCase); } else { return matchPattern(pattern, subject); } } else { return matchPattern(pattern, subject); } }; if (pattern.Contains(';')) { string[] parts = pattern.Split(';'); for (int i=0; i