Directory.GetFilesが配列を返すので、列挙子にしてみる。特にSearchOption.AllDirectoriesが指定されると、処理が返って来るまでにかなり時間がかかることがある。
フォルダーは再帰探索する必要があるので、実装は少し捻る必要がある。
public static class LinqExtensions { public static IEnumerable<string> FilesAsEnumerable(string path, string patterns) { foreach (var directoryPath in Directory.GetDirectories(path, "*", SearchOption.TopDirectoryOnly)) { foreach (var filePath in FilesAsEnumerable(directoryPath, patterns)) { yield return filePath; } } foreach (var filePath in Directory.GetFiles(path, patterns, SearchOption.TopDirectoryOnly)) { yield return filePath; } } }
これでもいいのだが、foreachだらけで見通しが悪い。全てクエリに置き換える。
public static class LinqExtensions { public static IEnumerable<string> FilesAsEnumerable(string path, string patterns) { var byDirectory = from directoryPath in Directory.GetDirectories(path, "*", SearchOption.TopDirectoryOnly) from filePath in FilesAsEnumerable(directoryPath, patterns) select filePath; var byFile = from filePath in Directory.GetFiles(path, patterns, SearchOption.TopDirectoryOnly) select filePath; return byDirectory.Concat(byFile); } }
これでファイルの列挙は以下のように記述できる。
foreach (var path in LinqExtensions.FilesAsEnumerable(@"C:project", "*.cs")) { Console.WriteLine(path); }
ファイルの逐次探索が可能になったので、大量のファイルをパイプライン処理できるようになった。
なお、このコードは.NET 4.0以降では、Directory.EnumerateFilesとほぼ同じ動作となる。