获取最大目录深度

本文关键字:深度 获取 | 更新日期: 2023-09-27 18:37:17

我只是想知道,是否有一种快速的解决方案可以获取根目录中最深文件夹的级别。

假设我使用"C:''"然后我需要一个函数,它可以让我获得根目录中"最深"文件夹的级别数,而无需遍历每个目录。

获取最大目录深度

最好的办法是递归地使用 System.IO.DirectoryInfo GetDirectories。确保不要使用SearchOption.AllDirectories因为那样会肯定会因安全错误而中断!

static List<string> directories = new List<string>();
        static void GetDirectories(string path)
        {
            try
            {
                foreach (var directory in Directory.GetDirectories(path))
                {
                    var di = new DirectoryInfo(directory);
                    directories.Add(di.FullName);
                    GetDirectories(di.FullName);
                }
            }
            catch (UnauthorizedAccessException uaex) { }
            catch (PathTooLongException ptlex) { }
            catch (Exception ex) { }
        }
static void Main(string[] args)
    {
        var path = @"C:'";
        GetDirectories(path);
        var maxLevel = directories.Max(d => d.Split('''').Count());
        var deepest = directories.Select(d => new
            {
                Path = d,
                Levels = d.Split('''').Count()
            })
        .OrderByDescending(d => d.Levels)
        .First();
    }

但是你会遇到一个PathTooLongException,看看这个问题如何解决这个问题。

我对PathTooLongException感到困扰,并提出了这个:

public static class DirectoryEx
{
    static char driveLetter;
    static string longPath;
    static List<string> directories;
    static DirectoryEx()
    {
        longPath = String.Empty;
    }
    private static char GetAvailableDrive()
    {
        var all = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray().Reverse();
        var occupied = DriveInfo.GetDrives()
            .OrderByDescending(d => d.Name)
            .Select(d => (char)d.Name.ToUpper().First());
        var free = all.Except(occupied).First();
        return free;
    }
    public static List<string> GetDirectories(string path)
    {
        directories = new List<string>();
        // recursive call
        FindDirectories(path);
        return directories;
    }
    static void FindDirectories(string path)
    {
        try
        {
            foreach (var directory in Directory.GetDirectories(path))
            {
                var di = new DirectoryInfo(directory);
                if(!String.IsNullOrEmpty(longPath))
                    directories.Add(di.FullName.Replace(driveLetter + ":''", longPath + "''"));
                else
                    directories.Add(di.FullName);
                FindDirectories(di.FullName);
            }
        }
        catch (UnauthorizedAccessException uaex) { Debug.WriteLine(uaex.Message); }
        catch (PathTooLongException ptlex)
        {
            Debug.WriteLine(ptlex.Message);
            longPath = path;
            Task t = new Task(new Action(() =>
            {
                CreateVirtualDrive(longPath);
                FindDirectories(driveLetter + ":''");
                DeleteVirtualDrive();
                longPath = String.Empty;
            }));
            if (!String.IsNullOrEmpty(longPath))
                t.RunSynchronously();
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message); 
        }
    }
    static void CreateVirtualDrive(string path)
    {
        driveLetter = GetAvailableDrive();
        Process.Start(new ProcessStartInfo() {
            FileName = "cmd.exe",
            WindowStyle = ProcessWindowStyle.Hidden,
            Arguments = String.Format("/c subst {0}: {1}", driveLetter.ToString(), path)
        });
        while (!DriveInfo.GetDrives().Select(d => d.Name.ToUpper().First()).Contains(driveLetter))
        {
            System.Threading.Thread.Sleep(1);
        }
    }
    static void DeleteVirtualDrive()
    {
        Process.Start(new ProcessStartInfo()
        {
            FileName = "cmd.exe",
            WindowStyle = ProcessWindowStyle.Hidden,
            Arguments = String.Format("/c subst {0}: /D", driveLetter.ToString())
        });
        while (DriveInfo.GetDrives().Select(d => d.Name.ToUpper().First()).Contains(driveLetter))
        {
            System.Threading.Thread.Sleep(1);
        }
    }
}

用作var directories = DirectoryEx.GetDirectories("C:''");

这将为每个太长的路径创建一个虚拟驱动器(使用 SUBST),以便它仍然可以遍历它。需要优化,可以扩展以提供一些DirectoryInfo包装类。