Dexter
Dexter

Reputation: 18452

List all folders which match defined path pattern

I need to perform some operations on all folders within a file share which match a defined pattern. The pattern may refer to a number of levels in the tree, e.g. \Test\[a-z]+\Project[0-9]{3}

What is the most efficient way to traverse the tree to find all matching folders? Is there a better way to do this than a simple recursive depth first search using DirectoryInfo and di.GetDirectories(), like such:

private void TraverseSubFolder(DirectoryInfo folder)
{
    if (filter.IsMatch(folder.FullName)) {
       DoStuff(folder);
    }

    DirectoryInfo[] subFolders = folder.GetDirectories();
    foreach (DirectoryInfo sf in subFolders)
    {
        TraverseSubFolder(sf);
    }
}

Upvotes: 3

Views: 3534

Answers (2)

Pierre-Alain Vigeant
Pierre-Alain Vigeant

Reputation: 23103

You could use Linq to filter

Regex regex = new Regex("your regex");
var directories = Directory.GetDirectories("c:\\", null, SearchOption.AllDirectories).Where(directory => regex.IsMatch(directory));

The drawback of this approach is that it will still search into unwanted folder that were filtered out since the Where occurs after all folders are returned.

This could be adapted.

Edit

This will not work with SearchOption.AllDirectories since as soon as you hit a folder where you have no right, UnauthorizedAccessException will be thrown.

I don't think you can go without a recursive function because of the check for UnauthorizedAccessException.

I coded this approach using Linq, but it is not very different from your own approach. At least it check for permission. It is still prone to a StackOverflowException.

private static void Traverse(List<string> folders, string rootFolder, Regex filter)
{
    try
    {
        // Test for UnauthorizedAccessException
        new FileIOPermission(FileIOPermissionAccess.PathDiscovery, rootFolder).Demand();

        Array.ForEach(Directory.GetDirectories(rootFolder),
            (directory) =>
            {
                if (filter.IsMatch(directory))
                {
                    folders.Add(directory);

                    Traverse(folders, directory, filter);
                }
            });
    }
    catch 
    {
        // Ignore folder that we don't have access to
    }
}

// Usage example
List<string> folders = new List<string>();
Regex regex = new Regex("^.+$");
Traverse(folders, "e:\\projects", regex);

Upvotes: 4

Nestor
Nestor

Reputation: 13990

Directory.GetDirectories(..,.., SearchOption.AllDirectories)

Upvotes: 0

Related Questions