すべてのサブディレクトリ内の特定の拡張子を持つファイルの数を検索します
質問
Directory.GetFiles() または同様のメソッドですべての結果をループすることなく、特定の種類のファイルの数を見つける方法はありますか?私は次のようなものを探しています:
int ComponentCount = MagicFindFileCount(@"c:\windows\system32", "*.dll");
Directory.GetFiles を呼び出す再帰関数を作成できることはわかっていますが、すべての反復を行わずにこれを実行できれば、はるかにクリーンになります。
編集: 自分自身で再帰して反復することなくこれを行うことができない場合、それを行うための最良の方法は何でしょうか?
解決
を使用する必要があります。 Directory.GetFiles(パス、検索パターン、検索オプション) Directory.GetFiles() のオーバーロード。
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 のこのオーバーロードを使用できます。
そして、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;
}
けれど ジョンの解決策 のほうが良いかもしれません。
親ディレクトリ内のディレクトリとファイルの数を生成するアプリがあります。一部のディレクトリには、それぞれに数千のファイルを含む数千のサブディレクトリが含まれています。応答性の高い UI を維持しながらこれを行うには、次の操作を行います (パスを ディレクトリパスが選択されました 方法):
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);
}
}
}
誰かが反復部分を実行する必要があります。
私の知る限り、.NET にはそのようなメソッドはすでに存在しないため、誰かがあなたである必要があると思います。