在这种方法中,如果我没弄错的话,它会搜索文件内部。 所以当我输入searchTerm例如" Form1"它找到了46个文件。
但是现在我想在没有searchTerm的情况下更改方法,因此它将遍历所有文件,但最后我想得到所有文件类型的List。如果有相同的dupilcate不要将它们添加到List中,那么最后我会得到一个List,文件类型项目如:cs,txt,xml所以我会知道有哪些文件类型。
IEnumerable<string> SearchAccessibleFiles(string root, string searchTerm)
{
var files = new List<string>();
foreach (var file in Directory.EnumerateFiles(root).Where(m => m.Contains(searchTerm)))
{
files.Add(file);
}
foreach (var subDir in Directory.EnumerateDirectories(root))
{
try
{
files.AddRange(SearchAccessibleFiles(subDir, searchTerm));
}
catch (UnauthorizedAccessException ex)
{
// ...
}
}
return files;
}
问题在于,如果我只是制作GetFiles并且根目录是c:\那么当它到达windows 10中的目录时它将停止并且不会获得任何文件:Documents and设置
Directory.GetFiles(textBox3.Text, "*.*", SearchOption.AllDirectories).ToList();
由于我没有找到解决Directory.GetFiles的方法来传递这个目录,我试图使用递归方法。
答案 0 :(得分:1)
您可以使用extension = Path.GetExtension(fileName);
获取文件扩展名,并在文件列表中使用.Distinct()
删除重复项:
IEnumerable<string> SearchAccessibleFiles(string root, string searchTerm)
{
var files = new List<string>();
foreach (var file in Directory.EnumerateFiles(root).Where(m => m.Contains(searchTerm)))
{
string extension = Path.GetExtension(file);
files.Add(extension);
}
foreach (var subDir in Directory.EnumerateDirectories(root))
{
try
{
files.AddRange(SearchAccessibleFiles(subDir, searchTerm));
}
catch (UnauthorizedAccessException ex)
{
// ...
}
}
return files.Distinct().ToList();
}
您只需删除.Where(m => m.Contains(searchTerm))
部分,无需搜索字词即可进行搜索。
修改的
如果您不想使用.Distict()
并希望随时查看重复项,可以尝试以下方法:
IEnumerable<string> SearchAccessibleFilesNoDistinct(string root, List<string> files)
{
if(files == null)
files = new List<string>();
foreach (var file in Directory.EnumerateFiles(root))
{
string extension = Path.GetExtension(file);
if(!files.Containes(extension))
files.Add(extension);
}
foreach (var subDir in Directory.EnumerateDirectories(root))
{
try
{
SearchAccessibleFilesNoDistinct(subDir, files);
}
catch (UnauthorizedAccessException ex)
{
// ...
}
}
return files;
}
并且第一次通话看起来像这样:
var extensionsList = SearchAccessibleFilesNoDistinct("rootAddress",null);
你可以看到我通过递归方法传递文件列表,通过这种方法我们有相同的文件列表,在所有递归调用中都应该这样做,请记住在递归调用中没有必要得到返回的列表已经有了相同的列表,但最后我们可以使用返回的列表进一步使用。 希望有所帮助
答案 1 :(得分:1)
问题可分为几个部分:
(1)递归枚举所有可访问的目录
(2)枚举多个目录文件
(3)获取不同的文件扩展名
请注意,只有(3)是特定的,(1)和(2)是通用的,可以用于其他处理(如SearchAccessibleFiles
等)。所以让我们分别解决它们:
(1)递归枚举所有可访问的目录:
这又可以分为两部分:
(A)递归枚举通用树结构
(B)上述可访问目录树的专业化
对于(A)我个人使用我对How to flatten tree via LINQ?及类似答案的帮助方法:
public static class TreeUtils
{
public static IEnumerable<T> Expand<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> elementSelector)
{
var stack = new Stack<IEnumerator<T>>();
var e = source.GetEnumerator();
try
{
while (true)
{
while (e.MoveNext())
{
var item = e.Current;
yield return item;
var elements = elementSelector(item);
if (elements == null) continue;
stack.Push(e);
e = elements.GetEnumerator();
}
if (stack.Count == 0) break;
e.Dispose();
e = stack.Pop();
}
}
finally
{
e.Dispose();
while (stack.Count != 0) stack.Pop().Dispose();
}
}
}
以下是我们案例的专业化:
public static partial class DirectoryUtils
{
public static IEnumerable<DirectoryInfo> EnumerateAccessibleDirectories(string path, bool all = false)
{
var filter = Func((IEnumerable<DirectoryInfo> source) =>
source.Select(di =>
{
try { return new { Info = di, Children = di.EnumerateDirectories() }; }
catch (UnauthorizedAccessException) { return null; }
})
.Where(e => e != null));
var items = filter(Enumerable.Repeat(new DirectoryInfo(path), 1));
if (all)
items = items.Expand(e => filter(e.Children));
else
items = items.Concat(items.SelectMany(e => filter(e.Children)));
return items.Select(e => e.Info);
}
static Func<T, TResult> Func<T, TResult>(Func<T, TResult> func) { return func; }
}
(2)枚举多个目录文件:
消除重复代码的简单扩展方法:
partial class DirectoryUtils
{
public static IEnumerable<FileInfo> EnumerateAccessibleFiles(string path, bool allDirectories = false)
{
return EnumerateAccessibleDirectories(path, allDirectories).EnumerateFiles();
}
public static IEnumerable<FileInfo> EnumerateFiles(this IEnumerable<DirectoryInfo> source)
{
return source.SelectMany(di => di.EnumerateFiles());
}
}
(3)获取不同的文件扩展名
使用上面的帮助程序,这是一个简单的LINQ查询问题:
var result = DirectoryUtils.EnumerateAccessibleFiles(rootPath, true)
.Select(file => file.Extension).Distinct()
.ToList();
最后,为了进行比较,以下是使用相同帮助程序时原始方法的外观:
IEnumerable<string> SearchAccessibleFiles(string root, string searchTerm)
{
return DirectoryUtils.EnumerateAccessibleFiles(rootPath, true)
.Where(file => file.FullName.Contains(searchTerm))
.Select(file => file.FullName);
}
如果搜索字词不包含目录信息,则可以将过滤条件更改为file.Name.Contains(searchTerm)
。