views:

112

answers:

3

I've got a function that currently grabs all folders and sub-folders to check the ACL's for a small tool I'm building but I'm pulling my hair out trying to figure out how to limit the depth that it can go to. For example you have a folder that goes 4 levels deep but I want to be able to only grab 3 levels of it for ACL's.

Currently I have it coded thusly:

private void StepThroughDirectories(string dir)
{
    string[] directories = Directory.GetDirectories(dir);
    try
    {
        foreach (string d in Directory.GetDirectories(dir))
        {
            if (recCount < (int)Depth)
            {
                GetACLs(d, new DirectoryInfo(d));
                pBar.Value += 1;
                //MessageBox.Show("Recursive Level: " + counter.ToString());
                recCount++;
                StepThroughDirectories(d);
            }
            else
            {
                recCount--;
            }
        }
    }
    catch (System.Exception e)
    {
        Console.WriteLine(e.Message);
    }
}

Obviously that's not as nice as it was because I've been working on the problem for a little while but if anyone can point me in the right direction to solve this issue I would be very happy!

+4  A: 

One possible method, add a class field outside your method and a variable to indicate how many levels deep to go max.

int levels;

private void StepThroughDirectories(string dir, int depth)
{
    levels ++;
    if (levels > depth)
        return;
    string[] directories = Directory.GetDirectories(dir);
    try
    { ...
Beaner
Actually, `levels` doesn't represent the depth, but the number of `StepThroughDirectories` calls.
digEmAll
Downside of this is that you cannot have two calls to StepThroughDirectories in progress at once (since levels sould be shared). Maybe not an issue in this applicatiom but Ondrej Tucny's solution is more self contained and cleaner.
Paul
@Paul Good point. I didn't think about that while answering.
Beaner
+2  A: 

Decrement recCount when you return from StepThroughDirectories, but this would be better...

    private void StepThroughDirectories(string dir, int depth)
    {
        if (depth < 0)
            return;
        string[] directories = Directory.GetDirectories(dir);
        try
        {
            foreach (string d in Directory.GetDirectories(dir))
            {
                // your code here
                Console.WriteLine("{0}", d);
                StepThroughDirectories(d, depth-1);
            }
        }
        catch (System.Exception e)
        {
            Console.WriteLine(e.Message);
        }
    } 
Les
Well, yes, that's the source of the error which I didn't notice at first. However, the design is a bit clumsy, so some refactoring to make it more readable and manageable would be advisory as well.
Ondrej Tucny
Edited my post to add my proposed refactor
Les
All suggestions posted so far seem to agree in that passing the state down the recursion is a recommended practice, better cohesion, decreased coupling (to globals).
Les
+10  A: 

First, avoid declaring the recCount field outside as a “global” variable. In recursive scenarios it's usually more manageable to pass state along the recursive calls.

Second, move the depth test out of the foreach to remove unnecessary querying of the file system for subdirectories.

Third, place the actual processing logic at the beginning of your method, again out of the subdirectories processing loop.

Your code would then look like:

void StepThroughDirectories(string dir)
{
    StepThroughDirectories(dir, 0)
}

void StepThroughDirectories(string dir, int currentDept)
{
    // process 'dir'
    ...

    // process subdirectories
    if (currentDepth < MaximumDepth)
    {
        foreach (string subdird in Directory.GetDirectories(dir))
            StepThroughDirectories(subdir, currentDepth + 1);
    }
}
Ondrej Tucny
You just saved me an afternoon headache! Thank you!
Jeff
Great to hear that, I'm glad my solution helped you.
Ondrej Tucny
Rather than passing currentDepth, my normal preference would be to pass depthLimit, which would count down rather than up.
supercat
@supercat Good point, thanks.
Ondrej Tucny
@Ondrej Just curious, where does MaximumDepth come from?
Beaner
@Beaner In-line with the original example I expect `MacimumDepth` to be declared as a constant or property somewhere else — e.g. in the surrounding class.
Ondrej Tucny