Searching
dazinator opened this issue · 1 comments
dazinator commented
It would be nice to be able to Search for a bunch of IFileInfo's using a pattern.
I have implemented this as an extension method - would you consider adding something like this in future?
// ReSharper disable once CheckNamespace
// Extension method put in root namespace for discoverability purposes.
public static class IFileProviderExtensions
{
/// <summary>
/// returns all items in the directory that match the specified glob pattern.
/// </summary>
/// <param name="globPattern"></param>
/// <returns></returns>
public static IEnumerable<IFileInfo> Search(this IFileProvider fileProvider, string globPattern)
{
var results = new GlobMatchingEnumerableFileInfos(fileProvider, globPattern);
return results;
}
}
public class GlobMatchingEnumerableFileInfos : IEnumerable<IFileInfo>
{
private readonly IFileProvider _fileProvider;
private readonly string _pattern;
public GlobMatchingEnumerableFileInfos(IFileProvider fileProvider, string pattern)
{
_fileProvider = fileProvider;
_pattern = pattern;
}
public IEnumerator<IFileInfo> GetEnumerator()
{
var folders = new Stack<KeyValuePair<string, IFileInfo>>();
var glob = new Glob(_pattern); // this is an open source glob matcher I am using. You will no doubt have your own glob pattern matching implementation...
var folderPath = "";
var currentFolder = _fileProvider.GetDirectoryContents("");
while (currentFolder != null)
{
foreach (var item in currentFolder)
{
var itemPath = $"{folderPath}/{item.Name}";
var isMatch = glob.IsMatch(itemPath);
if (isMatch)
{
yield return item;
}
if (item.IsDirectory)
{
// add the nested folder to a queue for later processing its items in the loop.
folders.Push(new KeyValuePair<string, IFileInfo>(itemPath, item));
continue;
}
}
if (folders.Count > 0)
{
var folderItem = folders.Pop();
folderPath = folderItem.Key;
currentFolder = _fileProvider.GetDirectoryContents(folderPath);
}
else
{
// finished iteating entire directory.
currentFolder = null;
}
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
Then usage is like:
IFileInfo[] results = fileProvider.Search("*.js").ToArray();
This type of cuntionality is useful for instance when watching using a pattern.
For example if watching "/js/*.js" - when that change tolen is signalled, there is no way to know which particular file caused the token to be signalled. Therefore you have to re-query the file provider to get all the files that match the pattern. This is where a Search("pattern") function would come in handy.
aspnet-hello commented
This issue was moved to dotnet/aspnetcore#2545