Menu

- Learn
- Documentation
  - Language Reference
  - Library Reference
  - Command-line Reference
  - Feature Overview
  - Articles
- Downloads
- Packages
- Community
  - Blog
  - Orgs using D
  - Twitter
  - Forums
  - IRC
  - Wiki
  - GitHub
  - Issues
  - Get involved
  - Contributors
  - Foundation
  - Donate
- Resources
  - Books
  - Tutorials
  - Tools
  - Editors
  - IDEs
  - Visual D
  - Acknowledgments
  - D Style
  - Glossary
  - Sitemap

Search
Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

# std.path

This module is used to manipulate path strings.
All functions, with the exception of expandTilde (and in some cases absolutePath and relativePath), are pure string manipulation functions; they don't depend on any state outside the program, nor do they perform any actual file system actions. This has the consequence that the module does not make any distinction between a path that points to a directory and a path that points to a file, and it does not know whether or not the object pointed to by the path actually exists in the file system. To differentiate between these cases, use std.file.isDir and std.file.exists.
Note that on Windows, both the backslash (\) and the slash (/) are in principle valid directory separators. This module treats them both on equal footing, but in cases where a new separator is added, a backslash will be used. Furthermore, the buildNormalizedPath function will replace all slashes with backslashes on that platform.
In general, the functions in this module assume that the input paths are well-formed. (That is, they should not contain invalid characters, they should follow the file system's path format, etc.) The result of calling a function on an ill-formed path is undefined. When there is a chance that a path or a file name is invalid (for instance, when it has been input by the user), it may sometimes be desirable to use the isValidFilename and isValidPath functions to check this.
Most functions do not perform any memory allocations, and if a string is returned, it is usually a slice of an input string. If a function allocates, this is explicitly mentioned in the documentation.

Category | Functions
--- | ---
Normalization | absolutePath asAbsolutePath asNormalizedPath asRelativePath buildNormalizedPath buildPath chainPath expandTilde
Partitioning | baseName dirName dirSeparator driveName pathSeparator pathSplitter relativePath rootName stripDrive
Validation | isAbsolute isDirSeparator isRooted isValidFilename isValidPath
Extension | defaultExtension extension setExtension stripExtension withDefaultExtension withExtension
Other | filenameCharCmp filenameCmp globMatch CaseSensitive

Authors:
Lars Tandle Kyllingstad, Walter Bright, Grzegorz Adam Hankiewicz, Thomas Kühne, Andrei Alexandrescu
License:
Boost License 1.0

Source std/path.d

enum string `dirSeparator`;
  String used to separate directory names in a path. Under POSIX this is a slash, under Windows a backslash.
enum string `pathSeparator`;
  Path separator string. A colon under POSIX, a semicolon under Windows.
pure nothrow @nogc @safe bool `isDirSeparator`(dchar `c`);
  Determines whether the given character is a directory separator.
  On Windows, this includes both \ and /. On POSIX, it's just /.
enum `CaseSensitive`: bool;
  This enum is used as a template argument to functions which compare file names, and determines whether the comparison is case sensitive or not.
  `no`
    File names are case insensitive
  `yes`
    File names are case sensitive
  `osDefault`
    The default (or most common) setting for the current platform. That is, no on Windows and Mac OS X, and yes on all POSIX systems except OS X (Linux, *BSD, etc.).
auto `baseName`(R)(R `path`)
if (isRandomAccessRange!R && hasSlicing!R && isSomeChar!(ElementType!R) && !isSomeString!R);
auto `baseName`(C)(C[] `path`)
if (isSomeChar!C);
pure @safe inout(C)[] `baseName`(CaseSensitive cs = CaseSensitive.osDefault, C, C1)(inout(C)[] `path`, in C1[] `suffix`)
if (isSomeChar!C && isSomeChar!C1);
  Parameters:

  cs | Whether or not `suffix` matching is case-sensitive.
  R `path` | A `path` name. It can be a string, or any random-access range of characters.
  C1[] `suffix` | An optional `suffix` to be removed from the file name.

  Returns:
  The name of the file in the `path` name, without any leading directory and with an optional `suffix` chopped off.
  If `suffix` is specified, it will be compared to `path` using filenameCmp!cs, where cs is an optional template parameter determining whether the comparison is case sensitive or not. See the filenameCmp documentation for details.

  Example

      assert(baseName("dir/file.ext")         == "file.ext");
      assert(baseName("dir/file.ext", ".ext") == "file");
      assert(baseName("dir/file.ext", ".xyz") == "file.ext");
      assert(baseName("dir/filename", "name") == "file");
      assert(baseName("dir/subdir/")          == "subdir");

      version (Windows)
      {
          assert(baseName(`d:file.ext`)      == "file.ext");
          assert(baseName(`d:\dir\file.ext`) == "file.ext");
      }

  Note This function only strips away the specified `suffix`, which doesn't necessarily have to represent an extension. To remove the extension from a `path`, regardless of what the extension is, use stripExtension. To obtain the filename without leading directories and without an extension, combine the functions like this:

      assert(baseName(stripExtension("dir/file.ext")) == "file");

  Standards:
  This function complies with the POSIX requirements for the 'basename' shell utility (with suitable adaptations for Windows paths).
auto `dirName`(R)(R `path`)
if (isRandomAccessRange!R && hasSlicing!R && hasLength!R && isSomeChar!(ElementType!R) && !isSomeString!R);
auto `dirName`(C)(C[] `path`)
if (isSomeChar!C);
  Returns the directory part of a `path`. On Windows, this includes the drive letter if present.
  Parameters:

  R `path` | A `path` name.

  Returns:
  A slice of `path` or ".".
  Standards:
  This function complies with the POSIX requirements for the 'dirname' shell utility (with suitable adaptations for Windows paths).
auto `rootName`(R)(R `path`)
if ((isRandomAccessRange!R && hasSlicing!R && hasLength!R && isSomeChar!(ElementType!R) || isNarrowString!R) && !isConvertibleToString!R);
  Returns the root directory of the specified `path`, or `null` if the `path` is not rooted.
  Parameters:

  R `path` | A `path` name.

  Returns:
  A slice of `path`.
  Examples:

      assert(rootName("") is null);
      assert(rootName("foo") is null);
      writeln(rootName("/")); // "/"
      writeln(rootName("/foo/bar")); // "/"

      version (Windows)
      {
          assert(rootName("d:foo") is null);
          writeln(rootName(`d:\foo`)); // `d:\`
          writeln(rootName(`\\server\share\foo`)); // `\\server\share`
          writeln(rootName(`\\server\share`)); // `\\server\share`
      }

auto `driveName`(R)(R `path`)
if ((isRandomAccessRange!R && hasSlicing!R && hasLength!R && isSomeChar!(ElementType!R) || isNarrowString!R) && !isConvertibleToString!R);
  Get the drive portion of a `path`.
  Parameters:

  R `path` | string or range of characters

  Returns:
  A slice of path that is the drive, or an empty range if the drive is not specified. In the case of UNC paths, the network share is returned.
  Always returns an empty range on POSIX.
  Examples:

      import std.range : empty;
      version (Posix)  assert(driveName("c:/foo").empty);
      version (Windows)
      {
          assert(driveName(`dir\file`).empty);
          writeln(driveName(`d:file`)); // "d:"
          writeln(driveName(`d:\file`)); // "d:"
          writeln(driveName("d:")); // "d:"
          writeln(driveName(`\\server\share\file`)); // `\\server\share`
          writeln(driveName(`\\server\share\`)); // `\\server\share`
          writeln(driveName(`\\server\share`)); // `\\server\share`

          static assert(driveName(`d:\file`) == "d:");
      }

auto `stripDrive`(R)(R `path`)
if ((isRandomAccessRange!R && hasSlicing!R && isSomeChar!(ElementType!R) || isNarrowString!R) && !isConvertibleToString!R);
  Strips the drive from a Windows `path`. On POSIX, the `path` is returned unaltered.
  Parameters:

  R `path` | A pathname

  Returns:
  A slice of `path` without the drive component.
  Examples:

      version (Windows)
      {
          writeln(stripDrive(`d:\dir\file`)); // `\dir\file`
          writeln(stripDrive(`\\server\share\dir\file`)); // `\dir\file`
      }

auto `extension`(R)(R `path`)
if (isRandomAccessRange!R && hasSlicing!R && isSomeChar!(ElementType!R) || is(StringTypeOf!R));
  Parameters:

  R `path` | A `path` name.

  Returns:
  The extension part of a file name, including the dot.
  If there is no extension, `null` is returned.
  Examples:

      import std.range : empty;
      assert(extension("file").empty);
      writeln(extension("file.")); // "."
      writeln(extension("file.ext"w)); // ".ext"
      writeln(extension("file.ext1.ext2"d)); // ".ext2"
      assert(extension(".foo".dup).empty);
      writeln(extension(".foo.ext"w.dup)); // ".ext"

      static assert(extension("file").empty);
      static assert(extension("file.ext") == ".ext");

auto `stripExtension`(R)(R `path`)
if ((isRandomAccessRange!R && hasSlicing!R && hasLength!R && isSomeChar!(ElementType!R) || isNarrowString!R) && !isConvertibleToString!R);
  Remove extension from `path`.
  Parameters:

  R `path` | string or range to be sliced

  Returns:
  slice of `path` with the extension (if any) stripped off
  Examples:

      writeln(stripExtension("file")); // "file"
      writeln(stripExtension("file.ext")); // "file"
      writeln(stripExtension("file.ext1.ext2")); // "file.ext1"
      writeln(stripExtension("file.")); // "file"
      writeln(stripExtension(".file")); // ".file"
      writeln(stripExtension(".file.ext")); // ".file"
      writeln(stripExtension("dir/file.ext")); // "dir/file"

immutable(Unqual!C1)[] `setExtension`(C1, C2)(in C1[] `path`, in C2[] `ext`)
if (isSomeChar!C1 && !is(C1 == immutable) && is(Unqual!C1 == Unqual!C2));
immutable(C1)[] `setExtension`(C1, C2)(immutable(C1)[] `path`, const(C2)[] `ext`)
if (isSomeChar!C1 && is(Unqual!C1 == Unqual!C2));
  Sets or replaces an extension.
  If the filename already has an extension, it is replaced. If not, the extension is simply appended to the filename. Including a leading dot in `ext` is optional.
  If the extension is empty, this function is equivalent to stripExtension.
  This function normally allocates a new string (the possible exception being the case when `path` is immutable and doesn't already have an extension).
  Parameters:

  C1[] `path` | A `path` name
  C2[] `ext` | The new extension

  Returns:
  A string containing the path given by `path`, but where the extension has been set to `ext`.
  See Also:
  withExtension which does not allocate and returns a lazy range.
  Examples:

      writeln(setExtension("file", "ext")); // "file.ext"
      writeln(setExtension("file"w, ".ext"w)); // "file.ext"
      writeln(setExtension("file."d, "ext"d)); // "file.ext"
      writeln(setExtension("file.", ".ext")); // "file.ext"
      writeln(setExtension("file.old"w, "new"w)); // "file.new"
      writeln(setExtension("file.old"d, ".new"d)); // "file.new"

auto `withExtension`(R, C)(R `path`, C[] `ext`)
if ((isRandomAccessRange!R && hasSlicing!R && hasLength!R && isSomeChar!(ElementType!R) || isNarrowString!R) && !isConvertibleToString!R && isSomeChar!C);
  Replace existing extension on filespec with new one.
  Parameters:

  R `path` | string or random access range representing a filespec
  C[] `ext` | the new extension

  Returns:
  Range with `path`'s extension (if any) replaced with `ext`. The element encoding type of the returned range will be the same as `path`'s.
  See Also:
  setExtension
  Examples:

      import std.array;
      writeln(withExtension("file", "ext").array); // "file.ext"
      writeln(withExtension("file"w, ".ext"w).array); // "file.ext"
      writeln(withExtension("file.ext"w, ".").array); // "file."

      import std.utf : byChar, byWchar;
      writeln(withExtension("file".byChar, "ext").array); // "file.ext"
      writeln(withExtension("file"w.byWchar, ".ext"w).array); // "file.ext"w
      writeln(withExtension("file.ext"w.byWchar, ".").array); // "file."w

immutable(Unqual!C1)[] `defaultExtension`(C1, C2)(in C1[] `path`, in C2[] `ext`)
if (isSomeChar!C1 && is(Unqual!C1 == Unqual!C2));
  Parameters:

  C1[] `path` | A `path` name.
  C2[] `ext` | The default extension to use.

  Returns:
  The path given by `path`, with the extension given by `ext` appended if the `path` doesn't already have one.
  Including the dot in the extension is optional.
  This function always allocates a new string, except in the case when `path` is immutable and already has an extension.
  Examples:

      writeln(defaultExtension("file", "ext")); // "file.ext"
      writeln(defaultExtension("file", ".ext")); // "file.ext"
      writeln(defaultExtension("file.", "ext")); // "file."
      writeln(defaultExtension("file.old", "new")); // "file.old"
      writeln(defaultExtension("file.old", ".new")); // "file.old"

auto `withDefaultExtension`(R, C)(R `path`, C[] `ext`)
if ((isRandomAccessRange!R && hasSlicing!R && hasLength!R && isSomeChar!(ElementType!R) || isNarrowString!R) && !isConvertibleToString!R && isSomeChar!C);
  Set the extension of `path` to `ext` if `path` doesn't have one.
  Parameters:

  R `path` | filespec as string or range
  C[] `ext` | extension, may have leading '.'

  Returns:
  range with the result
  Examples:

      import std.array;
      writeln(withDefaultExtension("file", "ext").array); // "file.ext"
      writeln(withDefaultExtension("file"w, ".ext").array); // "file.ext"w
      writeln(withDefaultExtension("file.", "ext").array); // "file."
      writeln(withDefaultExtension("file", "").array); // "file."

      import std.utf : byChar, byWchar;
      writeln(withDefaultExtension("file".byChar, "ext").array); // "file.ext"
      writeln(withDefaultExtension("file"w.byWchar, ".ext").array); // "file.ext"w
      writeln(withDefaultExtension("file.".byChar, "ext"d).array); // "file."
      writeln(withDefaultExtension("file".byChar, "").array); // "file."

immutable(ElementEncodingType!(ElementType!Range))[] `buildPath`(Range)(Range `segments`)
if (isInputRange!Range && !isInfinite!Range && isSomeString!(ElementType!Range));
pure nothrow @safe immutable(C)[] `buildPath`(C)(const(C)[][] `paths`...)
if (isSomeChar!C);
  Combines one or more path `segments`.
  This function takes a set of path `segments`, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between `segments` if necessary. If any of the path `segments` are absolute (as defined by isAbsolute), the preceding `segments` will be dropped.
  On Windows, if one of the path `segments` are rooted, but not absolute (e.g. \foo), all preceding path `segments` down to the previous root will be dropped. (See below for an example.)
  This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if `paths` is a forward range.
  Parameters:

  Range `segments` | An input range of `segments` to assemble the path from.

  Returns:
  The assembled path.
  Examples:

      version (Posix)
      {
          writeln(buildPath("foo", "bar", "baz")); // "foo/bar/baz"
          writeln(buildPath("/foo/", "bar/baz")); // "/foo/bar/baz"
          writeln(buildPath("/foo", "/bar")); // "/bar"
      }

      version (Windows)
      {
          writeln(buildPath("foo", "bar", "baz")); // `foo\bar\baz`
          writeln(buildPath(`c:\foo`, `bar\baz`)); // `c:\foo\bar\baz`
          writeln(buildPath("foo", `d:\bar`)); // `d:\bar`
          writeln(buildPath("foo", `\bar`)); // `\bar`
          writeln(buildPath(`c:\foo`, `\bar`)); // `c:\bar`
      }

auto `chainPath`(R1, R2, Ranges...)(R1 `r1`, R2 `r2`, Ranges `ranges`)
if ((isRandomAccessRange!R1 && hasSlicing!R1 && hasLength!R1 && isSomeChar!(ElementType!R1) || isNarrowString!R1 && !isConvertibleToString!R1) && (isRandomAccessRange!R2 && hasSlicing!R2 && hasLength!R2 && isSomeChar!(ElementType!R2) || isNarrowString!R2 && !isConvertibleToString!R2) && (Ranges.length == 0 || is(typeof(`chainPath`(`r2`, `ranges`)))));
  Concatenate path segments together to form one path.
  Parameters:

  R1 `r1` | first segment
  R2 `r2` | second segment
  Ranges `ranges` | 0 or more segments

  Returns:
  Lazy range which is the concatenation of `r1`, `r2` and `ranges` with path separators. The resulting element type is that of `r1`.
  See Also:
  buildPath
  Examples:

      import std.array;
      version (Posix)
      {
          writeln(chainPath("foo", "bar", "baz").array); // "foo/bar/baz"
          writeln(chainPath("/foo/", "bar/baz").array); // "/foo/bar/baz"
          writeln(chainPath("/foo", "/bar").array); // "/bar"
      }

      version (Windows)
      {
          writeln(chainPath("foo", "bar", "baz").array); // `foo\bar\baz`
          writeln(chainPath(`c:\foo`, `bar\baz`).array); // `c:\foo\bar\baz`
          writeln(chainPath("foo", `d:\bar`).array); // `d:\bar`
          writeln(chainPath("foo", `\bar`).array); // `\bar`
          writeln(chainPath(`c:\foo`, `\bar`).array); // `c:\bar`
      }

      import std.utf : byChar;
      version (Posix)
      {
          writeln(chainPath("foo", "bar", "baz").array); // "foo/bar/baz"
          writeln(chainPath("/foo/".byChar, "bar/baz").array); // "/foo/bar/baz"
          writeln(chainPath("/foo", "/bar".byChar).array); // "/bar"
      }

      version (Windows)
      {
          writeln(chainPath("foo", "bar", "baz").array); // `foo\bar\baz`
          writeln(chainPath(`c:\foo`.byChar, `bar\baz`).array); // `c:\foo\bar\baz`
          writeln(chainPath("foo", `d:\bar`).array); // `d:\bar`
          writeln(chainPath("foo", `\bar`.byChar).array); // `\bar`
          writeln(chainPath(`c:\foo`, `\bar`w).array); // `c:\bar`
      }

pure nothrow @trusted immutable(C)[] `buildNormalizedPath`(C)(const(C[])[] `paths`...)
if (isSomeChar!C);
  Performs the same task as buildPath, while at the same time resolving current/parent directory symbols ("." and "..") and removing superfluous directory separators. It will return "." if the path leads to the starting directory. On Windows, slashes are replaced with backslashes.
  Using `buildNormalizedPath` on `null` `paths` will always return `null`.
  Note that this function does not resolve symbolic links.
  This function always allocates memory to hold the resulting path. Use asNormalizedPath to not allocate memory.
  Parameters:

  const(C[])[] `paths` | An array of `paths` to assemble.

  Returns:
  The assembled path.
  Examples:

      writeln(buildNormalizedPath("foo", "..")); // "."

      version (Posix)
      {
          writeln(buildNormalizedPath("/foo/./bar/..//baz/")); // "/foo/baz"
          writeln(buildNormalizedPath("../foo/.")); // "../foo"
          writeln(buildNormalizedPath("/foo", "bar/baz/")); // "/foo/bar/baz"
          writeln(buildNormalizedPath("/foo", "/bar/..", "baz")); // "/baz"
          writeln(buildNormalizedPath("foo/./bar", "../../", "../baz")); // "../baz"
          writeln(buildNormalizedPath("/foo/./bar", "../../baz")); // "/baz"
      }

      version (Windows)
      {
          writeln(buildNormalizedPath(`c:\foo\.\bar/..\\baz\`)); // `c:\foo\baz`
          writeln(buildNormalizedPath(`..\foo\.`)); // `..\foo`
          writeln(buildNormalizedPath(`c:\foo`, `bar\baz\`)); // `c:\foo\bar\baz`
          writeln(buildNormalizedPath(`c:\foo`, `bar/..`)); // `c:\foo`
          assert(buildNormalizedPath(`\\server\share\foo`, `..\bar`) ==
                  `\\server\share\bar`);
      }

auto `asNormalizedPath`(R)(R `path`)
if (isSomeChar!(ElementEncodingType!R) && (isRandomAccessRange!R && hasSlicing!R && hasLength!R || isNarrowString!R) && !isConvertibleToString!R);
  Normalize a `path` by resolving current/parent directory symbols ("." and "..") and removing superfluous directory separators. It will return "." if the `path` leads to the starting directory. On Windows, slashes are replaced with backslashes.
  Using `asNormalizedPath` on empty paths will always return an empty `path`.
  Does not resolve symbolic links.
  This function always allocates memory to hold the resulting `path`. Use buildNormalizedPath to allocate memory and return a string.
  Parameters:

  R `path` | string or random access range representing the path to normalize

  Returns:
  normalized `path` as a forward range
  Examples:

      import std.array;
      writeln(asNormalizedPath("foo/..").array); // "."

      version (Posix)
      {
          writeln(asNormalizedPath("/foo/./bar/..//baz/").array); // "/foo/baz"
          writeln(asNormalizedPath("../foo/.").array); // "../foo"
          writeln(asNormalizedPath("/foo/bar/baz/").array); // "/foo/bar/baz"
          writeln(asNormalizedPath("/foo/./bar/../../baz").array); // "/baz"
      }

      version (Windows)
      {
          writeln(asNormalizedPath(`c:\foo\.\bar/..\\baz\`).array); // `c:\foo\baz`
          writeln(asNormalizedPath(`..\foo\.`).array); // `..\foo`
          writeln(asNormalizedPath(`c:\foo\bar\baz\`).array); // `c:\foo\bar\baz`
          writeln(asNormalizedPath(`c:\foo\bar/..`).array); // `c:\foo`
          assert(asNormalizedPath(`\\server\share\foo\..\bar`).array ==
                  `\\server\share\bar`);
      }

auto `pathSplitter`(R)(R `path`)
if ((isRandomAccessRange!R && hasSlicing!R || isNarrowString!R) && !isConvertibleToString!R);
  Slice up a `path` into its elements.
  Parameters:

  R `path` | string or slicable random access range

  Returns:
  bidirectional range of slices of `path`
  Examples:

      import std.algorithm.comparison : equal;
      import std.conv : to;

      assert(equal(pathSplitter("/"), ["/"]));
      assert(equal(pathSplitter("/foo/bar"), ["/", "foo", "bar"]));
      assert(equal(pathSplitter("foo/../bar//./"), ["foo", "..", "bar", "."]));

      version (Posix)
      {
          assert(equal(pathSplitter("//foo/bar"), ["/", "foo", "bar"]));
      }

      version (Windows)
      {
          assert(equal(pathSplitter(`foo\..\bar\/.\`), ["foo", "..", "bar", "."]));
          assert(equal(pathSplitter("c:"), ["c:"]));
          assert(equal(pathSplitter(`c:\foo\bar`), [`c:\`, "foo", "bar"]));
          assert(equal(pathSplitter(`c:foo\bar`), ["c:foo", "bar"]));
      }

bool `isRooted`(R)(R `path`)
if (isRandomAccessRange!R && isSomeChar!(ElementType!R) || is(StringTypeOf!R));
  Determines whether a `path` starts at a root directory.
  Parameters:

  R `path` | A `path` name.

  Returns:
  Whether a `path` starts at a root directory.
  On POSIX, this function returns `true` if and only if the `path` starts with a slash (/).

      version (Posix)
      {
          assert(isRooted("/"));
          assert(isRooted("/foo"));
          assert(!isRooted("foo"));
          assert(!isRooted("../foo"));
      }

  On Windows, this function returns `true` if the `path` starts at the root directory of the current drive, of some other drive, or of a network drive.

      version (Windows)
      {
          assert(isRooted(`\`));
          assert(isRooted(`\foo`));
          assert(isRooted(`d:\foo`));
          assert(isRooted(`\\foo\bar`));
          assert(!isRooted("foo"));
          assert(!isRooted("d:foo"));
      }

pure nothrow @safe bool `isAbsolute`(R)(R `path`)
if (isRandomAccessRange!R && isSomeChar!(ElementType!R) || is(StringTypeOf!R));
  Determines whether a `path` is absolute or not.
  Parameters:

  R `path` | A `path` name.

  Returns:
  Whether a `path` is absolute or not.

  Example On POSIX, an absolute `path` starts at the root directory. (In fact, isAbsolute is just an alias for isRooted.)

      version (Posix)
      {
          assert(isAbsolute("/"));
          assert(isAbsolute("/foo"));
          assert(!isAbsolute("foo"));
          assert(!isAbsolute("../foo"));
      }

  On Windows, an absolute `path` starts at the root directory of a specific drive. Hence, it must start with d:\ or d:/, where d is the drive letter. Alternatively, it may be a network `path`, i.e. a `path` starting with a double (back)slash.

      version (Windows)
      {
          assert(isAbsolute(`d:\`));
          assert(isAbsolute(`d:\foo`));
          assert(isAbsolute(`\\foo\bar`));
          assert(!isAbsolute(`\`));
          assert(!isAbsolute(`\foo`));
          assert(!isAbsolute("d:foo"));
      }

pure @safe string `absolutePath`(string `path`, lazy string `base` = getcwd());
  Transforms `path` into an absolute path.
  The following algorithm is used:
  1. If `path` is empty, return `null`.
  2. If `path` is already absolute, return it.
  3. Otherwise, append `path` to `base` and return the result. If `base` is not specified, the current working directory is used.
  The function allocates memory if and only if it gets to the third stage of this algorithm.
  Parameters:

  string `path` | the relative `path` to transform
  string `base` | the `base` directory of the relative `path`

  Returns:
  string of transformed `path`
  Throws:
  Exception if the specified base directory is not absolute.
  See Also:
  asAbsolutePath which does not allocate
  Examples:

      version (Posix)
      {
          writeln(absolutePath("some/file", "/foo/bar")); // "/foo/bar/some/file"
          writeln(absolutePath("../file", "/foo/bar")); // "/foo/bar/../file"
          writeln(absolutePath("/some/file", "/foo/bar")); // "/some/file"
      }

      version (Windows)
      {
          writeln(absolutePath(`some\file`, `c:\foo\bar`)); // `c:\foo\bar\some\file`
          writeln(absolutePath(`..\file`, `c:\foo\bar`)); // `c:\foo\bar\..\file`
          writeln(absolutePath(`c:\some\file`, `c:\foo\bar`)); // `c:\some\file`
          writeln(absolutePath(`\`, `c:\`)); // `c:\`
          writeln(absolutePath(`\some\file`, `c:\foo\bar`)); // `c:\some\file`
      }

auto `asAbsolutePath`(R)(R `path`)
if ((isRandomAccessRange!R && isSomeChar!(ElementType!R) || isNarrowString!R) && !isConvertibleToString!R);
  Transforms `path` into an absolute path.
  The following algorithm is used:
  1. If `path` is empty, return `null`.
  2. If `path` is already absolute, return it.
  3. Otherwise, append `path` to the current working directory, which allocates memory.
  Parameters:

  R `path` | the relative `path` to transform

  Returns:
  the transformed `path` as a lazy range
  See Also:
  absolutePath which returns an allocated string
  Examples:

      import std.array;
      writeln(asAbsolutePath(cast(string)null).array); // ""
      version (Posix)
      {
          writeln(asAbsolutePath("/foo").array); // "/foo"
      }
      version (Windows)
      {
          writeln(asAbsolutePath("c:/foo").array); // "c:/foo"
      }
      asAbsolutePath("foo");

string `relativePath`(CaseSensitive cs = CaseSensitive.osDefault)(string `path`, lazy string `base` = getcwd());
  Translates `path` into a relative path.
  The returned path is relative to `base`, which is by default taken to be the current working directory. If specified, `base` must be an absolute path, and it is always assumed to refer to a directory. If `path` and `base` refer to the same directory, the function returns ..
  The following algorithm is used:
  1. If `path` is a relative directory, return it unaltered.
  2. Find a common root between `path` and `base`. If there is no common root, return `path` unaltered.
  3. Prepare a string with as many ../ or ..\ as necessary to reach the common root from `base` `path`.
  4. Append the remaining segments of `path` to the string and return.
  In the second step, `path` components are compared using filenameCmp!cs, where cs is an optional template parameter determining whether the comparison is case sensitive or not. See the filenameCmp documentation for details.
  This function allocates memory.
  Parameters:

  cs | Whether matching `path` name components against the `base` `path` should be case-sensitive or not.
  string `path` | A `path` name.
  string `base` | The `base` `path` to construct the relative `path` from.

  Returns:
  The relative `path`.
  See Also:
  asRelativePath which does not allocate memory
  Throws:
  Exception if the specified base directory is not absolute.
  Examples:

      writeln(relativePath("foo")); // "foo"

      version (Posix)
      {
          writeln(relativePath("foo", "/bar")); // "foo"
          writeln(relativePath("/foo/bar", "/foo/bar")); // "."
          writeln(relativePath("/foo/bar", "/foo/baz")); // "../bar"
          writeln(relativePath("/foo/bar/baz", "/foo/woo/wee")); // "../../bar/baz"
          writeln(relativePath("/foo/bar/baz", "/foo/bar")); // "baz"
      }
      version (Windows)
      {
          writeln(relativePath("foo", `c:\bar`)); // "foo"
          writeln(relativePath(`c:\foo\bar`, `c:\foo\bar`)); // "."
          writeln(relativePath(`c:\foo\bar`, `c:\foo\baz`)); // `..\bar`
          writeln(relativePath(`c:\foo\bar\baz`, `c:\foo\woo\wee`)); // `..\..\bar\baz`
          writeln(relativePath(`c:\foo\bar\baz`, `c:\foo\bar`)); // "baz"
          writeln(relativePath(`c:\foo\bar`, `d:\foo`)); // `c:\foo\bar`
      }

auto `asRelativePath`(CaseSensitive cs = CaseSensitive.osDefault, R1, R2)(R1 `path`, R2 `base`)
if ((isNarrowString!R1 || isRandomAccessRange!R1 && hasSlicing!R1 && isSomeChar!(ElementType!R1) && !isConvertibleToString!R1) && (isNarrowString!R2 || isRandomAccessRange!R2 && hasSlicing!R2 && isSomeChar!(ElementType!R2) && !isConvertibleToString!R2));
  Transforms `path` into a path relative to `base`.
  The returned path is relative to `base`, which is usually the current working directory. `base` must be an absolute path, and it is always assumed to refer to a directory. If `path` and `base` refer to the same directory, the function returns '.'.
  The following algorithm is used:
  1. If `path` is a relative directory, return it unaltered.
  2. Find a common root between `path` and `base`. If there is no common root, return `path` unaltered.
  3. Prepare a string with as many ../ or ..\ as necessary to reach the common root from `base` `path`.
  4. Append the remaining segments of `path` to the string and return.
  In the second step, `path` components are compared using filenameCmp!cs, where cs is an optional template parameter determining whether the comparison is case sensitive or not. See the filenameCmp documentation for details.
  Parameters:

  R1 `path` | path to transform
  R2 `base` | absolute `path`
  cs | whether filespec comparisons are sensitive or not; defaults to CaseSensitive.osDefault

  Returns:
  a random access range of the transformed path
  See Also:
  relativePath
  Examples:

      import std.array;
      version (Posix)
      {
          writeln(asRelativePath("foo", "/bar").array); // "foo"
          writeln(asRelativePath("/foo/bar", "/foo/bar").array); // "."
          writeln(asRelativePath("/foo/bar", "/foo/baz").array); // "../bar"
          writeln(asRelativePath("/foo/bar/baz", "/foo/woo/wee").array); // "../../bar/baz"
          writeln(asRelativePath("/foo/bar/baz", "/foo/bar").array); // "baz"
      }
      else version (Windows)
      {
          writeln(asRelativePath("foo", `c:\bar`).array); // "foo"
          writeln(asRelativePath(`c:\foo\bar`, `c:\foo\bar`).array); // "."
          writeln(asRelativePath(`c:\foo\bar`, `c:\foo\baz`).array); // `..\bar`
          writeln(asRelativePath(`c:\foo\bar\baz`, `c:\foo\woo\wee`).array); // `..\..\bar\baz`
          writeln(asRelativePath(`c:/foo/bar/baz`, `c:\foo\woo\wee`).array); // `..\..\bar\baz`
          writeln(asRelativePath(`c:\foo\bar\baz`, `c:\foo\bar`).array); // "baz"
          writeln(asRelativePath(`c:\foo\bar`, `d:\foo`).array); // `c:\foo\bar`
          writeln(asRelativePath(`\\foo\bar`, `c:\foo`).array); // `\\foo\bar`
      }
      else
          static assert(0);

pure nothrow @safe int `filenameCharCmp`(CaseSensitive cs = CaseSensitive.osDefault)(dchar `a`, dchar `b`);
  Compares filename characters.
  This function can perform `a` case-sensitive or `a` case-insensitive comparison. This is controlled through the cs template parameter which, if not specified, is given by CaseSensitive.osDefault.
  On Windows, the backslash and slash characters (\ and /) are considered equal.
  Parameters:

  cs | Case-sensitivity of the comparison.
  dchar `a` | A filename character.
  dchar `b` | A filename character.

  Returns:
  < 0 if `a` < `b`, 0 if `a` == `b`, and > 0 if `a` > `b`.
  Examples:

      writeln(filenameCharCmp('a', 'a')); // 0
      assert(filenameCharCmp('a', 'b') < 0);
      assert(filenameCharCmp('b', 'a') > 0);

      version (linux)
      {
          // Same as calling filenameCharCmp!(CaseSensitive.yes)(a, b)
          assert(filenameCharCmp('A', 'a') < 0);
          assert(filenameCharCmp('a', 'A') > 0);
      }
      version (Windows)
      {
          // Same as calling filenameCharCmp!(CaseSensitive.no)(a, b)
          writeln(filenameCharCmp('a', 'A')); // 0
          assert(filenameCharCmp('a', 'B') < 0);
          assert(filenameCharCmp('A', 'b') < 0);
      }

int `filenameCmp`(CaseSensitive cs = CaseSensitive.osDefault, Range1, Range2)(Range1 `filename1`, Range2 `filename2`)
if (isInputRange!Range1 && !isInfinite!Range1 && isSomeChar!(ElementEncodingType!Range1) && !isConvertibleToString!Range1 && isInputRange!Range2 && !isInfinite!Range2 && isSomeChar!(ElementEncodingType!Range2) && !isConvertibleToString!Range2);
  Compares file names and returns
  Individual characters are compared using filenameCharCmp!cs, where cs is an optional template parameter determining whether the comparison is case sensitive or not.
  Treatment of invalid UTF encodings is implementation defined.
  Parameters:

  cs | case sensitivity
  Range1 `filename1` | range for first file name
  Range2 `filename2` | range for second file name

  Returns:
  < 0 if `filename1` < `filename2`, 0 if `filename1` == `filename2` and > 0 if `filename1` > `filename2`.
  See Also:
  filenameCharCmp
  Examples:

      writeln(filenameCmp("abc", "abc")); // 0
      assert(filenameCmp("abc", "abd") < 0);
      assert(filenameCmp("abc", "abb") > 0);
      assert(filenameCmp("abc", "abcd") < 0);
      assert(filenameCmp("abcd", "abc") > 0);

      version (linux)
      {
          // Same as calling filenameCmp!(CaseSensitive.yes)(filename1, filename2)
          assert(filenameCmp("Abc", "abc") < 0);
          assert(filenameCmp("abc", "Abc") > 0);
      }
      version (Windows)
      {
          // Same as calling filenameCmp!(CaseSensitive.no)(filename1, filename2)
          writeln(filenameCmp("Abc", "abc")); // 0
          writeln(filenameCmp("abc", "Abc")); // 0
          assert(filenameCmp("Abc", "abD") < 0);
          assert(filenameCmp("abc", "AbB") > 0);
      }

pure nothrow @safe bool `globMatch`(CaseSensitive cs = CaseSensitive.osDefault, C, Range)(Range `path`, const(C)[] `pattern`)
if (isForwardRange!Range && !isInfinite!Range && isSomeChar!(ElementEncodingType!Range) && !isConvertibleToString!Range && isSomeChar!C && is(Unqual!C == Unqual!(ElementEncodingType!Range)));
  Matches a `pattern` against a `path`.
  Some characters of `pattern` have a special meaning (they are meta-characters) and can't be escaped. These are:

  * | Matches 0 or more instances of any character.
  ? | Matches exactly one instance of any character.
  [chars] | Matches one instance of any character that appears between the brackets.
  [!chars] | Matches one instance of any character that does not appear between the brackets after the exclamation mark.
  {string1,string2,…} | Matches either of the specified strings.

  Individual characters are compared using filenameCharCmp!cs, where cs is an optional template parameter determining whether the comparison is case sensitive or not. See the filenameCharCmp documentation for details.
  Note that directory separators and dots don't stop a meta-character from matching further portions of the `path`.
  Parameters:

  cs | Whether the matching should be case-sensitive
  Range `path` | The `path` to be matched against
  const(C)[] `pattern` | The glob `pattern`

  Returns:
  `true` if `pattern` matches `path`, `false` otherwise.
  See Also:
  Wikipedia: glob (programming)
  Examples:

      assert(globMatch("foo.bar", "*"));
      assert(globMatch("foo.bar", "*.*"));
      assert(globMatch(`foo/foo\bar`, "f*b*r"));
      assert(globMatch("foo.bar", "f???bar"));
      assert(globMatch("foo.bar", "[fg]???bar"));
      assert(globMatch("foo.bar", "[!gh]*bar"));
      assert(globMatch("bar.fooz", "bar.{foo,bif}z"));
      assert(globMatch("bar.bifz", "bar.{foo,bif}z"));

      version (Windows)
      {
          // Same as calling globMatch!(CaseSensitive.no)(path, pattern)
          assert(globMatch("foo", "Foo"));
          assert(globMatch("Goo.bar", "[fg]???bar"));
      }
      version (linux)
      {
          // Same as calling globMatch!(CaseSensitive.yes)(path, pattern)
          assert(!globMatch("foo", "Foo"));
          assert(!globMatch("Goo.bar", "[fg]???bar"));
      }

bool `isValidFilename`(Range)(Range `filename`)
if ((isRandomAccessRange!Range && hasLength!Range && hasSlicing!Range && isSomeChar!(ElementEncodingType!Range) || isNarrowString!Range) && !isConvertibleToString!Range);
  Checks that the given file or directory name is valid.
  The maximum length of `filename` is given by the constant core.stdc.stdio.FILENAME_MAX. (On Windows, this number is defined as the maximum number of UTF-16 code points, and the test will therefore only yield strictly correct results when `filename` is a string of wchars.)
  On Windows, the following criteria must be satisfied (source):
  - `filename` must not contain any characters whose integer representation is in the range 0-31.
  - `filename` must not contain any of the following reserved characters: <>:"/\|?*
  - `filename` may not end with a space (' ') or a period ('.').
  On POSIX, `filename` may not contain a forward slash ('/') or the `null` character ('\0').
  Parameters:

  Range `filename` | string to check

  Returns:
  `true` if and only if `filename` is not empty, not too long, and does not contain invalid characters.
  Examples:

      import std.utf : byCodeUnit;

      assert(isValidFilename("hello.exe".byCodeUnit));

bool `isValidPath`(Range)(Range `path`)
if ((isRandomAccessRange!Range && hasLength!Range && hasSlicing!Range && isSomeChar!(ElementEncodingType!Range) || isNarrowString!Range) && !isConvertibleToString!Range);
  Checks whether `path` is a valid path.
  Generally, this function checks that `path` is not empty, and that each component of the `path` either satisfies isValidFilename or is equal to "." or "..".
  It does not check whether the path points to an existing file or directory; use std.file.exists for this purpose.
  On Windows, some special rules apply:
  - If the second character of `path` is a colon (':'), the first character is interpreted as a drive letter, and must be in the range A-Z (case insensitive).
  - If `path` is on the form \\server\share\... (UNC `path`), isValidFilename is applied to server and share as well.
  - If `path` starts with \\?\ (long UNC `path`), the only requirement for the rest of the string is that it does not contain the `null` character.
  - If `path` starts with \\.\ (Win32 device namespace) this function returns `false`; such paths are beyond the scope of this module.
  Parameters:

  Range `path` | string or Range of characters to check

  Returns:
  `true` if `path` is a valid path.
  Examples:

      assert(isValidPath("/foo/bar"));
      assert(!isValidPath("/foo\0/bar"));
      assert(isValidPath("/"));
      assert(isValidPath("a"));

      version (Windows)
      {
          assert(isValidPath(`c:\`));
          assert(isValidPath(`c:\foo`));
          assert(isValidPath(`c:\foo\.\bar\\\..\`));
          assert(!isValidPath(`!:\foo`));
          assert(!isValidPath(`c::\foo`));
          assert(!isValidPath(`c:\foo?`));
          assert(!isValidPath(`c:\foo.`));

          assert(isValidPath(`\\server\share`));
          assert(isValidPath(`\\server\share\foo`));
          assert(isValidPath(`\\server\share\\foo`));
          assert(!isValidPath(`\\\server\share\foo`));
          assert(!isValidPath(`\\server\\share\foo`));
          assert(!isValidPath(`\\ser*er\share\foo`));
          assert(!isValidPath(`\\server\sha?e\foo`));
          assert(!isValidPath(`\\server\share\|oo`));

          assert(isValidPath(`\\?\<>:"?*|/\..\.`));
          assert(!isValidPath("\\\\?\\foo\0bar"));

          assert(!isValidPath(`\\.\PhysicalDisk1`));
          assert(!isValidPath(`\\`));
      }

      import std.utf : byCodeUnit;
      assert(isValidPath("/foo/bar".byCodeUnit));

nothrow string `expandTilde`(string `inputPath`);
  Performs tilde expansion in paths on POSIX systems. On Windows, this function does nothing.
  There are two ways of using tilde expansion in a path. One involves using the tilde alone or followed by a path separator. In this case, the tilde will be expanded with the value of the environment variable HOME. The second way is putting a username after the tilde (i.e. ~john/Mail). Here, the username will be searched for in the user database (i.e. /etc/passwd on Unix systems) and will expand to whatever path is stored there. The username is considered the string after the tilde ending at the first instance of a path separator.
  Note that using the ~user syntax may give different values from just ~ if the environment variable doesn't match the value stored in the user database.
  When the environment variable version is used, the path won't be modified if the environment variable doesn't exist or it is empty. When the database version is used, the path won't be modified if the user doesn't exist in the database or there is not enough memory to perform the query.
  This function performs several memory allocations.
  Parameters:

  string `inputPath` | The path name to expand.

  Returns:
  `inputPath` with the tilde expanded, or just `inputPath` if it could not be expanded. For Windows, `expandTilde` merely returns its argument `inputPath`.

  Example

      void processFile(string path)
      {
          // Allow calling this function with paths such as ~/foo
          auto fullPath = expandTilde(path);
          ...
      }

Copyright © 1999-2018 by the D Language Foundation | Page generated by Ddoc on Thu Feb 15 22:05:23 2018