8

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!

2
  • What isn't working for you? Looks like this code doesn't compile - where's recCount declared (and pBar, and Depth)? and your (commented out) MessageBox.Show uses counter instead.... Commented Oct 6, 2010 at 16:06
  • there is an overload method that accepts EnumerationOptions. So you can call it with desired depth level. E.g. Directory.GetDirectories(dir, new EnumerationOptions { MaxRecursionDepth = 1, RecurseSubdirectories = true }) Commented Apr 12, 2023 at 4:56

4 Answers 4

17

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 currentDepth) { // process 'dir' ... // process subdirectories if (currentDepth < MaximumDepth) { foreach (string subdir in Directory.GetDirectories(dir)) StepThroughDirectories(subdir, currentDepth + 1); } } 
Sign up to request clarification or add additional context in comments.

5 Comments

You just saved me an afternoon headache! Thank you!
Great to hear that, I'm glad my solution helped you.
Rather than passing currentDepth, my normal preference would be to pass depthLimit, which would count down rather than up.
@Ondrej Just curious, where does MaximumDepth come from?
@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.
4

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 { ... 

2 Comments

Actually, levels doesn't represent the depth, but the number of StepThroughDirectories calls.
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.
2

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); } } 

3 Comments

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.
Edited my post to add my proposed refactor
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).
0

.NET standard 1.3 added the Directory.EnumerateFiles method which has options to search recursively. .NET standard 2.1 added an override with an EnumerationOptions argument to customize the search.

Finally, .NET 6 added the MaxRecursionDepth property to EnumerationOptions which natively implements the feature the OP requests.

Therefore, to search all dll files at a max depth of 2 sublevels inside the target directory, for example, it is now very easy:

string targetFolder = @"PATH\TO\FOLDER\TO\SEARCH"; IEnumerable<string> files = Directory.EnumerateFiles( targetFolder, "*.dll", new EnumerationOptions() { RecurseSubdirectories = true, MaxRecursionDepth = 2, }); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.