简体   繁体   中英

How to EnumerateFiles to only 3 files directories in C#?

Currently I can only Enumeratefiles method all files or the source directory. I want it to go 3 subdirectory's deeper and then only check there.

For Example the second snippet will check only K:\\SourceFolder

The first example will check K:\\SourceFolder\\JobName\\Batches\\Folder1\\Folder11\\Images It will check all folders and therefore decreasing the performance and efficiency of the application.

I only need it to check too K:\\SourceFolder\\JobName\\Batches

This code goes too far:

            List<string> validFiles = new List<string>();
            List<string> files = Directory.EnumerateFiles(folderPath, "*.*", SearchOption.AllDirectories).ToList();
            foreach (var file in files)

This code doesn't go far enough:

           List<string> files = Directory.Enumeratefiles(directory)

Theres a few different methods we could use to tackle this task, so I'll list a few examples to help get started.

Using a loop to iterate all the folders and return only those at target depth:

List<string> ListFilesAtSpecificDepth(string rootPath, int targetDepth)
{   
    // Set the root folder before we start iterating through subfolders.
    var foldersAtCurrentDepth = Directory.EnumerateDirectories(rootPath).ToList(); // calling ToList will make the enumeration happen now.
    
    for (int currentDepth = 0; currentDepth < targetDepth; currentDepth++)
    {
        // Using select many is a clean way to select the subfolders for multiple root folders into a flat list.
        foldersAtCurrentDepth = foldersAtCurrentDepth.SelectMany(x => Directory.EnumerateDirectories(x)).ToList();
    }
    
    // After the loop we have a list of folders for the targetDepth only.
    // Select many again to get all the files for all the folders.
    return foldersAtCurrentDepth.SelectMany(x => Directory.EnumerateFiles(x, "*.*", SearchOption.TopDirectoryOnly)).ToList();
}

Another options is to use recursion to recall the same method until we reach the desired depth. This can be used to only return results at the target depth or all the results along the way, since above example does only target depth, I've decided to do all results for this one using a custom object to track the depth:

class FileSearchResult
{
    public string FilePath {get;set;}
    public int FolderDepthFromRoot {get;set;}
}

List<FileSearchResult> ListFilesUntilSpecificDepth(string rootPath, int maxDepth, int currentDepth = 0)
{
    // Add all the files at the current level along with extra details like the depth.
    var iterationResult = Directory.EnumerateFiles(rootPath, "*.*", SearchOption.TopDirectoryOnly)
        .Select(x => new FileSearchResult 
        {       
            FilePath = x,
            FolderDepthFromRoot = currentDepth
        }).ToList();

    if (currentDepth < maxDepth) // we need to go deeper.
    {
        var foldersUnderMe = Directory.EnumerateDirectories(rootPath);

        // Add all the results for subfolders recursively by calling the same method again.
        foreach (var subFolder in foldersUnderMe)
        {
            iterationResult.AddRange(ListFilesUntilSpecificDepth(subFolder, maxDepth, currentDepth + 1))
        }
    }
    
    return iterationResult;
}

With and example for both recursion and looping both covered, the last one I want to touch on is using the structure of the file system itself to help accomplish this task. So instead of managing our own loops or recursion we can use the original method to get all files recursively and then using the list of all results we can determine the depth. eg We know that '/' is a character used by the file system to delimit folders and that it's an illegal character to use in a folder or file name, so it should be pretty safe to use this marker to effectively count folders. In this example I'll use another custom class to track the results so it should effectively return the same results as the recursive method but with infinite depth.

class FileSearchResult
{
    public string FilePath { get; set; }
    public int FolderDepthFromRoot { get; set; }
}

List<FileSearchResult> ListFiles(string rootPath)
{
    var allFiles = Directory.EnumerateFiles(rootPath, "*.*", SearchOption.AllDirectories).ToList();
    int numberOfFoldersInRootPath = rootPath.Count(c => c == '\\'); // count how many backslashes in root path as a base.

    return allFiles.Select(filePath => new FileSearchResult 
    {
        FilePath = filePath,
        FolderDepthFromRoot = filePath.Count(c => c == '\\') - numberOfFoldersInRootPath
    }).ToList();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM