File System File System
File System File System
DocFX + Singulink = ♥

Search Results for

    Combining and Navigating Paths

    Overview

    Paths are immutable. Every "modification" returns a new path object. The library offers three ways to build new paths from existing ones:

    • The + operator for concise combine expressions.
    • Combine* methods with explicit overloads for strings or pre-parsed paths.
    • Navigation members (ParentDirectory, RootDirectory) for walking up.

    All combinations preserve type strength: combining an absolute directory with a relative file produces an absolute file, and so on.

    The + Operator

    IDirectoryPath defines + overloads for every relative path type:

    IAbsoluteDirectoryPath baseDir = DirectoryPath.GetAppBase();
    IRelativeDirectoryPath subDir = DirectoryPath.ParseRelative("logs");
    IRelativeFilePath logFile = FilePath.ParseRelative("today.log");
    
    IAbsoluteDirectoryPath logsDir = baseDir + subDir;       // IAbsoluteDirectoryPath
    IAbsoluteFilePath fullLogPath  = logsDir + logFile;      // IAbsoluteFilePath
    IAbsoluteFilePath inOneStep    = baseDir + (subDir + logFile);
    

    Return types are inferred from the operands. Absolute + relative produces absolute; relative + relative produces relative.

    Combine With a Pre-Parsed Path

    When you already have a relative path object, use Combine:

    IAbsoluteFilePath result = baseDir.Combine(logFile);
    

    This is identical to the + operator, just spelled out.

    Combine With a String

    When the relative segment is a string (e.g. read from configuration), use CombineDirectory or CombineFile. These overloads parse the string in one step:

    IAbsoluteFilePath cfgFile = baseDir.CombineFile("config/app.json");
    IAbsoluteDirectoryPath dataDir = baseDir.CombineDirectory("data");
    

    By default, the string is parsed using the parent's PathFormat and PathOptions.NoUnfriendlyNames. Override either:

    IAbsoluteFilePath portable = baseDir.CombineFile("data/users.json", PathFormat.Universal);
    IAbsoluteDirectoryPath relaxed = baseDir.CombineDirectory(rawDir, PathOptions.None);
    
    Tip

    If you'll combine the same relative path more than once, parse it into a IRelative*Path once and reuse it. Combining a parsed relative path is cheaper and skips re-validation.

    Generic Combine

    For code that works with arbitrary relative paths, Combine(IRelativePath) returns the unifying base type (IPath / IAbsolutePath / IRelativePath depending on the receiver). Pattern match on the result if you need the specific type:

    IAbsolutePath result = baseDir.Combine(someRelative);
    
    if (result is IAbsoluteFilePath file) { /* ... */ }
    

    Walking Upward: ParentDirectory

    Every path has a ParentDirectory. For files it's always the containing directory; for directories it's null when the path is a root or otherwise has no parent (check HasParentDirectory first).

    IAbsoluteFilePath cfg = FilePath.ParseAbsolute(@"C:\Apps\MyApp\config\app.json");
    IAbsoluteDirectoryPath cfgDir = cfg.ParentDirectory;       // C:\Apps\MyApp\config
    IAbsoluteDirectoryPath appDir = cfgDir.ParentDirectory!;   // C:\Apps\MyApp
    

    A common pattern: ensure a file's directory exists before writing to it:

    file.ParentDirectory.Create();   // creates the directory tree if missing
    using var stream = file.OpenStream(FileMode.Create);
    

    Walking to the Root

    Use RootDirectory (on absolute paths) to jump straight to the root, or loop with HasParentDirectory:

    IAbsoluteDirectoryPath root = cfg.RootDirectory;     // C:\
    
    IDirectoryPath current = cfg.ParentDirectory;
    while (current.HasParentDirectory)
        current = current.ParentDirectory!;
    

    GetLastExistingDirectory

    When working with a path that may not exist yet, GetLastExistingDirectory() walks up the path until it finds a directory that does:

    var maybeMissing = FilePath.ParseAbsolute(@"C:\Apps\NewApp\data\users.json");
    IAbsoluteDirectoryPath existing = maybeMissing.GetLastExistingDirectory();
    long free = existing.AvailableFreeSpace;   // useful for pre-flight checks
    

    See Drive and Disk Information for more on disk-space queries.

    Navigation in Relative Paths

    Relative paths can encode upward navigation with ... The library resolves these as far as possible during parsing:

    DirectoryPath.ParseRelative("a/b/../c");      // "a/c"
    DirectoryPath.ParseRelative("../../shared");  // "../../shared" (kept: can't resolve further)
    

    Navigating past the root of an absolute path is always an error (see Parsing Paths).

    Note

    Every path is normalized as part of parsing. After parsing, the PathDisplay you see is what the library will use everywhere; there is no separate "canonical form".

    Cross-Format Combines

    Combining works seamlessly when one side uses PathFormat.Universal:

    IRelativeFilePath portableCfg = FilePath.ParseRelative("config/app.json", PathFormat.Universal);
    IAbsoluteDirectoryPath baseDir = DirectoryPath.GetAppBase();   // current format
    IAbsoluteFilePath cfg = baseDir + portableCfg;                 // current format
    

    Combining two specific formats that don't match (e.g. Windows + Unix) is an error. See the table in Path Formats.

    Next Steps

    • File Names and Extensions: manipulate the trailing segment of a path.
    • Working with Directories: once you've combined a path, do something with it.
    © Singulink. All rights reserved.