std::filesystem::path::lexically_normal, std::filesystem::path::lexically_relative, std::filesystem::path::lexically_proximate

< cpp‎ | filesystem‎ | path
path lexically_normal() const;
(1) (since C++17)
path lexically_relative(const path& base) const;
(2) (since C++17)
path lexically_proximate(const path& base) const;
(3) (since C++17)
1) Returns *this converted to normal form in its generic format
2) Returns *this made relative to base.
  • First, if root_name() != base.root_name() || is_absolute() != base.is_absolute() || (!has_root_directory() && base.has_root_directory()), returns a default-constructed path.
  • Otherwise, first determines the first mismatched element of *this and base as if by auto [a, b] = mismatch(begin(), end(), base.begin(), base.end()), then
  • if a == end() and b == base.end(), returns path(".");
  • otherwise, if the number of dot-dot filename elements in [b, base.end()) is greater than the number of filename elements that are neither dot nor dot-dot, returns a default-constructed path.
  • otherwise returns an object composed from
  • a default-constructed path() followed by
  • as many applications of operator/=(path("..")) as there were filename elements in [b, base.end()) that are neither dot nor dot-dot minus number of dot-dot elements in that range, followed by
  • one application of operator/= for each element in the half-open range [a, end())
3) If the value of lexically_relative(base) is not an empty path, return it. Otherwise return *this.


[edit] Parameters


[edit] Return value

1) The normal form of the path
2) The relative form of the path
3) The proximate form of the path

[edit] Exceptions


[edit] Notes

These conversions are purely lexical. They do not check that the paths exist, do not follow symlinks, and do not access the filesystem at all. For symlink-following counterparts of lexically_relative and lexically_proximate, see relative and proximate.

On Windows, the returned path has backslashes (the preferred separators),

[edit] Example

#include <iostream>
#include <filesystem>
#include <cassert>
namespace fs = std::filesystem;
int main()
    assert(fs::path("foo/./bar/..").lexically_normal() == "foo/");
    assert(fs::path("foo/.///bar/../").lexically_normal() == "foo/");
    assert(path("/a/d").lexically_relative("/a/b/c") == "../../d");
    assert(path("/a/b/c").lexically_relative("/a/d") == "../b/c");
    assert(path("a/b/c").lexically_relative("a") == "b/c");
    assert(path("a/b/c").lexically_relative("a/b/c/x/y") == "../..");
    assert(path("a/b/c").lexically_relative("a/b/c") == ".");
    assert(path("a/b").lexically_relative("c/d") == "../../a/b");

[edit] See also

composes a relative path
(function) [edit]