ddn.os.path¶
The ddn.os.path module provides utilities for file and directory path manipulation. Heavily inspired by Python's pathlib, it offers a cross-platform Path struct for robust path handling on Windows, Linux, and other POSIX systems.
Overview¶
This module provides the Path struct, which encapsulates filesystem path operations in an object-oriented manner. Instead of working with raw strings and calling separate functions, you can use method chaining and operators to manipulate paths naturally.
The module builds upon and extends standard D path and file utilities, offering additional convenience functions for joining, splitting, normalizing, traversing, and querying filesystem paths.
Key Features¶
- Cross-Platform Support: Works on Windows, Linux, and POSIX systems
- Python pathlib-Inspired API: Familiar interface for Python developers
- Path Joining: Use the
/operator to join path components - Path Traversal: Navigate parent directories and ancestors
- Glob Patterns: Find files matching wildcard patterns
- Directory Walking: Recursively traverse directory trees
- File Operations: Read, write, copy, move, and delete files
- Symlink and Hardlink Support: Create and manage filesystem links
- File Metadata: Query ownership, permissions, and timestamps
Basic Usage¶
import ddn.os.path;
void main() {
// Create Path objects
auto p1 = Path("foo/bar/baz.txt");
auto p2 = Path("/tmp/example.txt");
// Get string representation
writeln(p1.str()); // "foo/bar/baz.txt"
// Join paths using / operator
auto joined = Path("foo") / "bar" / "baz.txt";
// Get absolute path
auto abs = p1.absolute();
// Get parent directory
auto parent = p1.parent(); // "foo/bar"
}
Path Components¶
Extract various components from a path:
import ddn.os.path;
auto p = Path("/home/user/documents/report.txt");
// File name (with extension)
p.name(); // "report.txt"
// Stem (file name without extension)
p.stem(); // "report"
// Extension/suffix
p.suffix(); // ".txt"
// Parent directory
p.parent(); // Path("/home/user/documents")
// All parent directories
foreach (par; p.parents()) {
writeln(par.str());
}
// Output:
// /home/user/documents
// /home/user
// /home
Path Joining¶
Join path components using the / operator or string concatenation:
import ddn.os.path;
// Using / operator
auto p1 = Path("/home") / "user" / "file.txt";
// Result: /home/user/file.txt
// Building paths incrementally
auto base = Path("/var/log");
auto logFile = base / "app" / "debug.log";
File System Queries¶
Check file existence and type:
import ddn.os.path;
auto p = Path("/tmp/myfile.txt");
// Check existence
if (p.exists()) {
// Check type
if (p.isFile()) {
writeln("It's a file");
} else if (p.isDir()) {
writeln("It's a directory");
} else if (p.isSymlink()) {
writeln("It's a symbolic link");
}
}
// Check if absolute path
if (p.isAbsolute()) { ... }
File Operations¶
Read and write files:
import ddn.os.path;
auto p = Path("example.txt");
// Write text to file
p.writeText("Hello, World!");
// Read text from file
string content = p.readText();
// Touch (create or update timestamp)
p.touch();
// Remove file
p.remove();
Directory Operations¶
Create and manage directories:
import ddn.os.path;
auto dir = Path("my/nested/directory");
// Create directory (including parents)
dir.mkdir(); // Creates all intermediate directories
// Remove empty directory
dir.rmdir();
// Remove directory and all contents
dir.remove(); // Recursive removal
Glob Patterns¶
Find files matching patterns:
import ddn.os.path;
auto dir = Path("/var/log");
// Find all .txt files in directory
auto txtFiles = dir.glob("*.txt");
// Find files in subdirectories
auto nestedTxt = dir.glob("**/*.txt");
// Find hidden files
auto hidden = dir.glob(".*");
// Recursive glob (shorthand for **/ prefix)
auto allLogs = dir.rglob("*.log");
Directory Walking¶
Traverse directory trees:
import ddn.os.path;
auto root = Path("/project");
// Walk directory tree (top-down by default)
foreach (entry; root.walk()) {
writeln("Directory: ", entry.root.str());
// Subdirectories in this directory
foreach (d; entry.dirs) {
writeln(" Subdir: ", d.str());
}
// Files in this directory
foreach (f; entry.files) {
writeln(" File: ", f.str());
}
}
// Walk bottom-up
foreach (entry; root.walk(false)) { ... }
// Follow symlinks
foreach (entry; root.walk(true, true)) { ... }
Symlinks and Hardlinks¶
Create filesystem links (POSIX):
import ddn.os.path;
auto target = Path("original.txt");
target.writeText("content");
// Create symbolic link
auto symlink = Path("link_to_original.txt");
symlink.symlinkTo(target.str());
// Create hard link
auto hardlink = Path("hardlink_to_original.txt");
hardlink.hardlinkTo(target.str());
// Read symlink target
string linkTarget = symlink.readlink();
Path Resolution and Normalization¶
import ddn.os.path;
auto p = Path("foo/bar/../baz/./file.txt");
// Resolve to absolute path with normalization
auto resolved = p.resolve();
// Removes . and .. components, makes absolute
// Get absolute path
auto abs = p.absolute();
// Normalize path (remove redundant separators and . / ..)
auto normalized = Path("foo//bar/./baz").normalize();
File Comparison¶
import ddn.os.path;
auto p1 = Path("/tmp/file1.txt");
auto p2 = Path("/tmp/file2.txt");
// Check if two paths refer to the same file
if (p1.samefile(p2)) {
writeln("Same file!");
}
File Metadata (POSIX)¶
import ddn.os.path;
auto p = Path("/etc/passwd");
// Get owner username
string owner = p.owner();
// Get group name
string group = p.group();
// Check special file types
p.isBlockDevice();
p.isCharDevice();
p.isFIFO();
p.isSocket();
Path Conversion¶
import ddn.os.path;
auto p = Path("/home/user/file.txt");
// Get string representation
string s = p.str();
// Use in string context (via alias this)
writeln(p); // Automatically converts to string
When to Use¶
Use this module when you need to:
- Manipulate filesystem paths in a cross-platform manner
- Build paths dynamically using intuitive operators
- Search for files using glob patterns
- Traverse directory trees recursively
- Perform file I/O operations with a clean API
- Work with symlinks and hardlinks
- Query file metadata and permissions