I have a files search function that iterates over a given directory until a given depth is reached and returns the found files. I did this via the Enumerate methods of the Directory class and yield return the results. Since it's very likely that I hit a directory that I can't access (e.g. system directories) or generate a too long path (if the depth is large), I have to catch the exceptions from these cases. However since I can't use yield
in try/catch statements, I find my code pretty bloated, because I have to seperate the critical method calls from the rest.
Is there a better/shorter way to do this, or are there best practices for that case?
private IEnumerable<string> SearchSubdirs(string currentDir, int currentDepth) {
IEnumerable<string> exeFiles;
try {
exeFiles = Directory.EnumerateFiles(currentDir, "*.exe");
}
catch (UnauthorizedAccessException uae) {
Debug.WriteLine(uae.Message);
yield break;
}
catch (PathTooLongException ptle) {
Debug.WriteLine(ptle.Message);
yield break;
}
foreach (string currentFile in exeFiles) {
// Ignore unistaller *.exe files
if (currentFile.IndexOf("unins", 0, StringComparison.CurrentCultureIgnoreCase) == -1) {
yield return currentFile;
}
}
if (currentDepth < maxDepth) {
IEnumerable<string> subDirectories;
currentDepth++;
try {
subDirectories = Directory.EnumerateDirectories(currentDir);
}
catch (UnauthorizedAccessException uae) {
Debug.WriteLine(uae.Message);
yield break;
}
catch (PathTooLongException ptle) {
Debug.WriteLine(ptle.Message);
yield break;
}
foreach (string subDir in subDirectories) {
foreach (string file in SearchSubdirs(subDir, currentDepth)) {
yield return file;
}
}
}
}
-
1\$\begingroup\$ msdn.microsoft.com/en-us/library/bb513869.aspx \$\endgroup\$Leonid– Leonid2013年03月05日 17:39:35 +00:00Commented Mar 5, 2013 at 17:39
-
1\$\begingroup\$ stackoverflow.com/questions/1393178/… \$\endgroup\$radarbob– radarbob2013年03月05日 18:43:33 +00:00Commented Mar 5, 2013 at 18:43
1 Answer 1
I would use Linq methods to simplify the code. Also I've extracted 2 methods to simplify the main method. And please rename GetFilesWeAreLookingFor
to whatever your find appropriate :).
private static IEnumerable<string> GetFilesWeAreLookingFor(string currentDir)
{
try
{
return Directory.EnumerateFiles(currentDir, "*.exe")
.Where(fileName => fileName.IndexOf("unins", 0, StringComparison.CurrentCultureIgnoreCase) == -1);
}
catch (UnauthorizedAccessException uae)
{
Debug.WriteLine(uae.Message);
}
catch (PathTooLongException ptle)
{
Debug.WriteLine(ptle.Message);
}
return Enumerable.Empty<string>();
}
private IEnumerable<string> GetNestedFiles(string currentDir, int nestedDepth)
{
try
{
return Directory.EnumerateDirectories(currentDir)
.SelectMany(subDirectory => SearchSubdirs(subDirectory, nestedDepth));
}
catch (UnauthorizedAccessException uae)
{
Debug.WriteLine(uae.Message);
}
catch (PathTooLongException ptle)
{
Debug.WriteLine(ptle.Message);
}
return Enumerable.Empty<string>();
}
private IEnumerable<string> SearchSubdirs(string currentDir, int currentDepth)
{
IEnumerable<string> filesWeAreLookingFor = GetFilesWeAreLookingFor(currentDir);
if (currentDepth < _maxDepth)
filesWeAreLookingFor = filesWeAreLookingFor.Concat(GetNestedFiles(currentDir, currentDepth + 1));
return filesWeAreLookingFor;
}