random-file-runner/RyzStudio/IO/SmartDirectory.cs

288 lines
8.7 KiB
C#
Raw Permalink Normal View History

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace RandomFileRunner.IO
{
public class SmartDirectory
{
2021-10-30 02:21:45 +00:00
public static List<string> GetFiles(string path, string pattern, bool searchTopOnly)
{
List<string> fileList = new List<string>();
List<string> directoryList = new List<string>();
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<string> searchDirList = new List<string>();
try
{
searchDirList = Directory.EnumerateDirectories(directory, "*", SearchOption.TopDirectoryOnly);
}
catch (Exception)
{
continue;
}
2021-10-30 02:21:45 +00:00
if (!searchTopOnly)
{
2021-10-30 02:21:45 +00:00
foreach (string item in searchDirList)
{
2021-10-30 02:21:45 +00:00
if (!IsDirectoryAccessible(item))
{
continue;
}
2021-10-30 02:21:45 +00:00
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;
}
2021-10-30 02:21:45 +00:00
public static void GetFiles(string path, string pattern, bool searchTopOnly, Func<string, ulong, int, bool> callback)
{
List<string> directoryList = new List<string>();
ulong searchCount = 0;
2021-10-27 01:04:11 +00:00
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<string> searchDirList = new List<string>();
try
{
searchDirList = Directory.EnumerateDirectories(directory, "*", SearchOption.TopDirectoryOnly);
}
catch (Exception)
{
continue;
}
2021-10-30 02:21:45 +00:00
if (!searchTopOnly)
{
2021-10-30 02:21:45 +00:00
foreach (string item in searchDirList)
{
2021-10-30 02:21:45 +00:00
if (!IsDirectoryAccessible(item))
{
continue;
}
2021-10-30 02:21:45 +00:00
directoryList.Add(item);
searchCount++;
2021-10-30 02:21:45 +00:00
callback(null, searchCount, directoryList.Count);
}
}
2021-10-27 01:04:11 +00:00
foreach (string item in Directory.EnumerateFiles(directory, "*", SearchOption.TopDirectoryOnly))
{
2021-10-27 01:04:11 +00:00
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;
}
2021-10-27 01:04:11 +00:00
public static bool MatchFileSearchPattern(string pattern, string subject)
{
2021-10-27 16:10:56 +00:00
if (string.IsNullOrWhiteSpace(pattern))
2021-10-27 01:04:11 +00:00
{
return false;
}
Func<string, string, bool> 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;
};
2021-10-27 16:10:56 +00:00
Func<string, string, bool> matchAllPattern = (pattern, subject) =>
2021-10-27 01:04:11 +00:00
{
2021-10-27 16:10:56 +00:00
int wildcardCount = pattern.Count(x => x.Equals('*'));
if (wildcardCount <= 0)
2021-10-27 01:04:11 +00:00
{
2021-10-27 16:10:56 +00:00
return subject.Equals(pattern, StringComparison.CurrentCultureIgnoreCase);
2021-10-27 01:04:11 +00:00
}
2021-10-27 16:10:56 +00:00
else if (wildcardCount == 1)
2021-10-27 01:04:11 +00:00
{
2021-10-27 16:10:56 +00:00
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);
}
2021-10-27 01:04:11 +00:00
}
else
{
2021-10-27 16:10:56 +00:00
return matchPattern(pattern, subject);
}
};
if (pattern.Contains(';'))
{
string[] parts = pattern.Split(';');
for (int i=0; i<parts.Length; i++)
{
if (string.IsNullOrWhiteSpace(parts[i]))
{
continue;
}
if (matchAllPattern(parts[i].Trim(), subject))
{
return true;
}
2021-10-27 01:04:11 +00:00
}
2021-10-27 16:10:56 +00:00
return false;
2021-10-27 01:04:11 +00:00
}
else
{
2021-10-27 16:10:56 +00:00
return matchAllPattern(pattern, subject);
2021-10-27 01:04:11 +00:00
}
}
}
}