Skip to content

Example: Path Globbing with ddn.os.path

This example demonstrates how to use the globbing features of the ddn.os.path module to match files and directories using patterns, similar to Python's pathlib or shell globbing.


Source: demo/os/path_glob.d

module demo.os.path_glob;

import std.stdio;
import std.file;
import std.path;
import std.algorithm;
import std.array;
import std.uuid : randomUUID;
import ddn.os.path;

void main() {
  writeln("=== ddn.os.path.glob demo ===");

  // Create a temporary directory tree
  auto base = buildPath("tmp_demo_glob_" ~ randomUUID().toString());
  scope (exit) { if (exists(base)) rmdirRecurse(base); }

  Path(buildPath(base, "dir", "sub")).mkdir(true);
  Path(buildPath(base, "x", "y", "z")).mkdir(true);
  Path(buildPath(base, ".dotdir")).mkdir(true);

  Path(buildPath(base, "a.txt")).writeText("A\n");
  Path(buildPath(base, "b.TXT")).writeText("B\n");
  Path(buildPath(base, ".hidden")).writeText("H\n");
  Path(buildPath(base, "dir", "file.txt")).writeText("DF\n");
  Path(buildPath(base, "dir", "sub", "file.txt")).writeText("SF\n");
  Path(buildPath(base, "x", "y", "z", "note.txt")).writeText("N\n");
  Path(buildPath(base, ".dotdir", "secret.txt")).writeText("S\n");

  auto root = Path(base);

  // Helper to sort and print relative paths
  auto printMatches = (string title, Path[] items) {
    auto baseAbs = absolutePath(base);
    auto rel = items.map!(p => relativePath(absolutePath(p.str()), baseAbs)).array;
    rel.sort();
    writeln("-- ", title);
    foreach (r; rel) writeln("  ", r);
  };

  // Basic: *.txt at root (dotfiles excluded)
  printMatches("*.txt", root.glob("*.txt"));

  // Hidden entries: use a segment that starts with '.'
  printMatches(".*", root.glob(".*"));

  // Multi-segment and recursive globbing
  printMatches("dir/*/*.txt", root.glob("dir/*/*.txt"));
  printMatches("**/*.txt", root.glob("**/*.txt"));

  // rglob convenience: find a specific file name anywhere
  printMatches("rglob(file.txt)", root.rglob("file.txt"));

  writeln("=== End glob demo ===");
}

What This Example Shows

  • Creating a directory tree with various files and subdirectories, including hidden files and directories.
  • Using glob patterns to match files:
  • *.txt matches all .txt files at the root.
  • .* matches hidden files and directories at the root.
  • dir/*/*.txt matches .txt files two levels deep under dir.
  • **/*.txt matches all .txt files recursively.
  • Using rglob to find all files named file.txt anywhere in the tree.
  • Sorting and displaying results relative to the base directory.

Example Output

=== ddn.os.path.glob demo ===
-- *.txt
  a.txt
  b.TXT
-- .*
  .dotdir
  .hidden
-- dir/*/*.txt
  dir/sub/file.txt
-- **/*.txt
  a.txt
  b.TXT
  dir/file.txt
  dir/sub/file.txt
  x/y/z/note.txt
  .dotdir/secret.txt
-- rglob(file.txt)
  dir/file.txt
  dir/sub/file.txt
=== End glob demo ===

Key Takeaways

  • The glob method supports wildcards (*), recursive patterns (**), and can match hidden files.
  • The rglob method is a shortcut for recursively finding files by name.
  • This approach is useful for file discovery, batch processing, and scripting tasks involving complex directory structures.

See also:
- Reference: ddn.os.path