在所有子目录中查找具有特定扩展名的文件数

有没有办法找到特定类型的文件数,而无需在Directory.GetFiles()或类似方法中循环遍历所有结果? 我正在寻找这样的东西:

int ComponentCount = MagicFindFileCount(@"c:\windows\system32", "*.dll"); 

我知道我可以创建一个递归函数来调用Directory.GetFiles,但是如果我可以在没有所有迭代的情况下执行此操作,那将会更加清晰。

编辑:如果没有递归和迭代自己不可能做到这一点,那么最好的方法是什么?

您应该使用Directory.GetFiles()的Directory.GetFiles(path,searchPattern,SearchOption)重载。

Path指定路径,searchPattern指定通配符(例如,*,*。format),SearchOption提供包含子目录的选项。

此搜索的返回数组的Length属性将为您的特定搜索模式和选项提供正确的文件计数:

 string[] files = directory.GetFiles(@"c:\windows\system32", "*.dll", SearchOption.AllDirectories); return files.Length; 

编辑:或者您可以使用Directory.EnumerateFiles方法

 return Directory.EnumerateFiles(@"c:\windows\system32", "*.dll", SearchOption.AllDirectories).Count(); 

最简单的方法是使用linq:

 var fileCount = (from file in Directory.EnumerateFiles(@"H:\iPod_Control\Music", "*.mp3", SearchOption.AllDirectories) select file).Count(); 

您可以使用GetFiles的这个重载:

Directory.GetFiles方法(String,String,SearchOption )

和SearchOption的这个成员:

AllDirectories – 包括搜索操作中的当前目录和所有子目录。 此选项包括重新分析点,如安装的驱动器和搜索中的符号链接。

GetFiles返回一个字符串数组,因此您只需获取Length,即找到的文件数。

我一直在寻找更优化的版本。 由于我还没有找到它,我决定编码并在此处分享:

  public static int GetFileCount(string path, string searchPattern, SearchOption searchOption) { var fileCount = 0; var fileIter = Directory.EnumerateFiles(path, searchPattern, searchOption); foreach (var file in fileIter) fileCount++; return fileCount; } 

使用GetFiles / GetDirectories的所有解决方案都很慢,因为需要创建所有这些对象。 使用枚举,它不会创建任何临时对象(FileInfo / DirectoryInfo)。

有关更多信息,请参阅备注http://msdn.microsoft.com/en-us/library/dd383571.aspx

使用递归,您的MagicFindFileCount将如下所示:

 private int MagicFindFileCount( string strDirectory, string strFilter ) { int nFiles = Directory.GetFiles( strDirectory, strFilter ).Length; foreach( String dir in Directory.GetDirectories( strDirectory ) ) { nFiles += GetNumberOfFiles(dir, strFilter); } return nFiles; } 

虽然乔恩的解决方案可能更好。

我有一个应用程序,它生成父目录中的目录和文件的计数。 一些目录包含数千个子目录,每个目录中包含数千个文件。 要在保持响应式ui的同时执行此操作,请执行以下操作(将路径发送到ADirectoryPathWasSelected方法):

 public class DirectoryFileCounter { int mDirectoriesToRead = 0; // Pass this method the parent directory path public void ADirectoryPathWasSelected(string path) { // create a task to do this in the background for responsive ui // state is the path Task.Factory.StartNew((state) => { try { // Get the first layer of sub directories this.AddCountFilesAndFolders(state.ToString()) } catch // Add Handlers for exceptions {} }, path)); } // This method is called recursively private void AddCountFilesAndFolders(string path) { try { // Only doing the top directory to prevent an exception from stopping the entire recursion var directories = Directory.EnumerateDirectories(path, "*.*", SearchOption.TopDirectoryOnly); // calling class is tracking the count of directories this.mDirectoriesToRead += directories.Count(); // get the child directories // this uses an extension method to the IEnumerable interface, // which will run a function on an object. In this case 'd' is the // collection of directories directories.ActionOnEnumerable(d => AddCountFilesAndFolders(d)); } catch // Add Handlers for exceptions { } try { // count the files in the directory this.mFilesToRead += Directory.EnumerateFiles(path).Count(); } catch// Add Handlers for exceptions { } } } // Extension class public static class Extensions { // this runs the supplied method on each object in the supplied enumerable public static void ActionOnEnumerable(this IEnumerable nodes,Action doit) { foreach (var node in nodes) { doit(node); } } } 

有人必须做迭代部分。

AFAIK,.NET中已经没有这样的方法,所以我想有人必须是你。