Найдите количество файлов с определенным расширением во всех подкаталогах
Вопрос
Есть ли способ найти количество файлов определенного типа без необходимости перебирать все результаты в каталоге.GetFiles() или аналогичный метод?Я ищу что-то вроде этого:
int ComponentCount = MagicFindFileCount(@"c:\windows\system32", "*.dll");
Я знаю, что могу создать рекурсивную функцию для вызова Directory.GetFiles , но было бы намного чище, если бы я мог сделать это без всех итераций.
Редактировать: Если невозможно сделать это без повторения и итерации самостоятельно, каков был бы наилучший способ сделать это?
Решение
Вам следует использовать Каталог.GetFiles(путь, searchPattern, SearchOption) перегрузка каталога.GetFiles().
Path указывает путь, searchPattern указывает ваши подстановочные знаки (например, *, *.format), а SearchOption предоставляет возможность включать подкаталоги.
Свойство Length возвращаемого массива этого поиска предоставит правильное количество файлов для вашего конкретного шаблона поиска и опции:
string[] files = directory.GetFiles(@"c:\windows\system32", "*.dll", SearchOption.AllDirectories);
return files.Length;
Редактировать: В качестве альтернативы вы можете использовать Каталог.Метод перечисления файлов
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:
Каталог.Метод получения файлов (String, Строка, параметр поиска)
и этот участник SearchOption:
Все каталоги - Включает текущий каталог и все подкаталоги в операции поиска.Этот параметр включает в себя точки повторной проверки, такие как подключенные диски и символические ссылки в поиске.
GetFiles возвращает массив строк, так что вы можете просто получить длину, которая равна количеству найденных файлов.
Я искал более оптимизированную версию.Поскольку я не нашел его, я решил закодировать и поделиться им здесь:
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;
}
Хотя Решение Джона возможно, это было бы лучше.
У меня есть приложение, которое генерирует количество каталогов и файлов в родительском каталоге.Некоторые каталоги содержат тысячи подкаталогов с тысячами файлов в каждом.Чтобы сделать это, сохраняя адаптивный пользовательский интерфейс, я делаю следующее ( отправляя путь к Выбранный adirectorypath способ):
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<V> 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<V>(this IEnumerable<V> nodes,Action<V> doit)
{
foreach (var node in nodes)
{
doit(node);
}
}
}
Кто-то должен выполнить повторяющуюся часть.
AFAIK, в .NET такого метода уже нет, так что я предполагаю, что кем-то должен быть ты.