0

I have a directory structure like this:

A: -
   B1 - C11 - D111 
        C12 - D121
              D122
   B2 - C21
        C22
        C23
        C24
   B3 - C31

Now, to get only the 2nd level directories, in PowerShell it's direct:

$LEVEL2 = get-childitem -Path 'A:\*\*'  | ?{ $_.PSIsContainer } 

This will give me:

C11, C12, C21, C22, C23, C24, C31

Now, I want to do this in c#. Can anyone help with that?

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • 1
    Does this answer your question? [Resolving relative paths with wildcards in C#](https://stackoverflow.com/questions/8517260/resolving-relative-paths-with-wildcards-in-c-sharp) – Jesse Jan 27 '20 at 05:46
  • No, actually I want a list of all the sub-directories, not a particular file type. – Vishwas Joshi Jan 27 '20 at 05:52
  • Then replace `Directory.GetFiles()` with `Directory.GetDirectories()` and don't put an extension in the pattern string. – Jesse Jan 27 '20 at 05:54
  • The linked post assume the pattern is just part of file name and doesn't answer this question. IO functions which have pattern matching like `Directory.EnumerateDirectories`, they apply the pattern on the name not the path. Here is this question, the pattern should apply If you want to rely on those functions, you first need to find the root from given pattern, then split the pattern by `\` and then for each level, use `EnumerateDirectories` by doing pattern matching by the split pattern. – Reza Aghaei Jan 27 '20 at 08:40
  • @VishwasJoshi The given PowerShell doesn't stop in 2nd level directories. It also return 3rd levels and deeper levels. Do you need pattern matching like what I did in the answer? Do you need 2nd levels and deeper or it should stop in the 2nd level? – Reza Aghaei Jan 27 '20 at 09:16
  • Yeah sure. I'm new to stack overflow and unfamiliar with the customs. I will do the needed. Thanks. – Vishwas Joshi Jan 31 '20 at 08:15
  • It does stop at level 2, I'm using that PowerShell code to get limited no. of sub-directories currently. I checked again and it works. get-childitem -Path 'A:\*\*' | ?{ $_.PSIsContainer } – Vishwas Joshi Jan 31 '20 at 08:20
  • No worries, thanks for the feedback. JFYI when you accept an answer it's recommended to to upvote it as well. It's not compulsory at all and I'm sharing it with you since I've noticed you have never upvoted an answer. Acceptance mark and Upvotes are at first place indicator for future readers to help them to find the useful answers faster. At the second place they are a token of appreciation by giving some reputations score to contributes. So it's always goof idea to consider doing so. – Reza Aghaei Jan 31 '20 at 08:28
  • Thanks. I'll keep that in mind. – Vishwas Joshi Jan 31 '20 at 11:35

3 Answers3

2

Assuming you have System.Linq and System.IO in scope, the simplest way would be:

Directory.EnumerateDirectories("A:\\").SelectMany(d => Directory.EnumerateDirectories(d))
yaakov
  • 5,552
  • 35
  • 48
1

I used the following method which supports * whildcard. Here is the algorithm, it checks if the path contains *, then from the left side of the *, it gets the last \ and consider the left side of \ as the root for search.

For example, the following search will return all directories in 2nd level of depth under c:\test:

var result = GetDirectories("c:\test\*\*");

Here is the function:

string[] GetDirectories(string path)
{
    var root = path;
    if (root.IndexOf('*') > -1)
        root = root.Substring(0, root.IndexOf('*'));
    if (root.LastIndexOf('\\') > -1)
        root = root.Substring(0, root.LastIndexOf('\\'));
    var all = Directory.GetDirectories(root, @"*", SearchOption.AllDirectories);
    var pattern = $"^{Regex.Escape(path).Replace("\\*", "[^\\\\]*")}$";
    return all.Where(x => Regex.IsMatch(x, pattern, RegexOptions.IgnoreCase)).ToArray();
}

The function needs some exception handling, for example for cases the resolved root doesn't exist. But in my tests it worked well for the following examples:

  • "c:\test\*" → All directories under c:\test\ path
  • "c:\test\a*" → All a* directories under c:\test\ path
  • "c:\test\a*\b*" → All b* directories under c:\test\a* path
  • "c:\test\a*\b" → All b directories under c:\test\a* path
  • "c:\test\*\*" → All directories two level depth under c:\test
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
0
class Program
{
   //Result Variable
    public static List<string> finalRes = new List<string>();
   //Level at which you want 
    public static int reqLevel = 3;

    static void Main(string[] args)
    {
        try
        {
            var path = @"D:\Personal\";
            GetFolederNames(path, 0);

        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }

    }

    public static void GetFolederNames(string path, int level)
    {

        var subDirs = new List<string>();
        subDirs = Directory.GetDirectories(path).ToList();
        if (level == reqLevel)
        {
            finalRes.Add(path);
            return;
        }
        foreach (var dir in subDirs)
        {
            if(finalRes.Contains(dir))
                continue;

            GetFolederNames(dir, level+1);
        }

    }
}
Sumit raj
  • 821
  • 1
  • 7
  • 14
  • Maybe you are answering [another question](https://stackoverflow.com/q/26709568/3110834). Current question needs pattern matching. – Reza Aghaei Jan 27 '20 at 08:52
  • 1
    @RezaAghaei He didn't specifically mention to use pattern matching. He only needs the directories at a particular level as far as I can understand. – Sumit raj Jan 27 '20 at 09:07