How to capture disk folder structure? What would be the shortest way to capture folder structure in code? I would like to have a more or less reusable strictly typed approach to use in scripts instead of stringly typed paths we all usually deal with. Here is how a part of my simple “system info” utility looks like:

static void Main(string[] args)
{
    foreach(var cursor in SystemDisk.Windows.Cursors.Animated)
        Console.WriteLine(cursor);
}   


Where:

using static System.IO.Directory;

public static class SystemDisk 
{        
    public static string Drive { get; set; } = "C:";
    public static string AutoexecBat =&gt; $"{Drive}\\Autoexec.bat";
    public static class Windows
    {
        public static string Path =&gt; $"{Drive}\\Windows";
        public static string SystemIni =&gt; $"{Path}\\System.ini";
        public static class Cursors
        {
            public static string Path =&gt; $"{Windows.Path}\\Cursors";
            public static IReadOnlyList&lt;string&gt; Animated =&gt; GetFiles(Path, "*.ani");
        }
    }
}
I've got the idea you're trying to achieve, however, this would be too much work to do if you're going to implement it this way. 

If you are still convinced that this is the only way, you can use struct and define the OS structure like you did, and keep it only for path something like this : 

public struct SystemDisk
{
    private static string Drive =&gt; Path.GetPathRoot(Environment.SystemDirectory);

    //using Refelction, will give you the object's full name, we then convert it to string and adjust it to be parsed as an OS path.
    private static string GetPath(Type type) =&gt; @Drive + @type.FullName.Substring(type.FullName.IndexOf('.') + "SystemDisk".Length + 2).Replace('+', Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar;

    public struct Windows
    {
        public static string Root =&gt; $@"{GetPath(typeof(Windows))}";

        public static string SystemIni =&gt; $@"{Root}System.ini";

        public struct System
        {
            public static string Root =&gt; $@"{GetPath(typeof(System))}";
        }

        public struct System32
        {
            public static string Root =&gt; $@"{GetPath(typeof(System32))}";
        }

        public struct Cursors
        {
            public static string Root =&gt; $@"{GetPath(typeof(Cursors))}";
            public static IReadOnlyList&lt;string&gt; Animated =&gt; GetFiles(Root, "*.ani");
        }
    }
}


if you're going to continue on this road, and you need to create a struct for each directory in the system folders, you can write a method to get the directories, and then design a model for it, then returning this model as string, then just copy and paste. To do that, you'll have to get first the directories, then get each directory name, after that, you'll remove any special chars from the name, then just make a  model template and pass the directory name to it, get the representative string, and copy / paste into the class. 

Here is method to camel case the name : 

public static string CamelCase(string str)
{
    str = str.Replace(".", " ").Replace("-", " ").Replace("_", " "); 

    return str.Contains(" ")
        ? string.Join("", str.Split(' ').Select(x =&gt; char.ToUpper(x[0]) + x.Substring(1)))
        : char.ToUpper(str[0]) + str.Substring(1);
}


now we can do a method to build the model template : 

public static string StructModelBuilder(string name, int indentlevel, string body = "")
{
    var sb = new StringBuilder(string.Empty);

    string indentLv1 = indentlevel == 0 ? string.Empty : new string(' ', indentlevel);

    string indentLv2 = indentLv1 == string.Empty ? new string(' ', 4) : new string(' ', indentlevel * 2);

    sb.Append(Environment.NewLine);
    sb.Append(indentLv1);
    sb.Append($"public struct {name}");
    sb.Append(Environment.NewLine);
    sb.Append(indentLv1);
    sb.Append("{");
    sb.Append(Environment.NewLine);
    sb.Append(indentLv2);
    sb.Append($"public static string Root =&gt; $@\"{{GetPath(typeof({name}))}}\";");
    sb.Append(Environment.NewLine);               
    sb.Append(body);           
    sb.Append(indentLv1);
    sb.Append("}");
    sb.Append(Environment.NewLine);

    return sb.ToString();
}


now, we can create a method where we get the directories list, and just pass them to the template to get the model

public static string GetStructureModel(string path)
{
    if (string.IsNullOrEmpty(path))
        return string.Empty;


    //Directory.GetDirectories($@"{path}", "*.*", SearchOption.AllDirectories);  // to include all sub-directories (recursively).
    var root_dir = Directory.GetDirectories($@"{path}");// just get the top level directories.

    // remove the last Directory Sparator Charcter (e.g. back-slash \) and get the name of the directory
    var root_name = path.TrimEnd('\\').Substring(path.LastIndexOf(System.IO.Path.DirectorySeparatorChar) + 1);

    var rootNameCamelCase = CamelCase(path.TrimEnd('\\'));

    var sb = new StringBuilder(string.Empty);

    var model = StructModelBuilder(rootNameCamelCase, 0, "@body");

    foreach (var dir in root_dir)
    {
        var dir_name = path.TrimEnd('\\').Substring(path.LastIndexOf(System.IO.Path.DirectorySeparatorChar) + 1);

        var dirNameCamelCase = CamelCase(dir_name);

        sb.Append(StructModelBuilder(dirNameCamelCase, 4));
    }

    return model.Replace("@body", sb.ToString());           
}


now you just pass the path like this : 

var model = GetStructureModel(@"C:\Windows");


you can from here take the model, paste it into the class, and adjust whatever needed. this is not perfect, but it should get the job done. 

personally, I wouldn't go this far if I were in your seat, instead, I'll use Window Environment Variables instead, to not re-invent the wheels. also, I'll make use of Enum and make things shorter. For instance, instead of making a full path to the System32, I'll just use an Enum and define System32, and with a simple switch statement, it'll return the full path, and so on. this would make more sense to me and would be easier to maintain.