# struct Path

- Path
- Struct
- Value
- Object

##
Overview

A `Path` represents a filesystem path and allows path-handling operations such as querying its components as well as semantic manipulations.

A path is hierarchical and composed of a sequence of directory and file name elements separated by a special separator or delimiter. A root component, that identifies a file system hierarchy, may also be present. The name element that is farthest from the root of the directory hierarchy is the name of a file or directory. The other name elements are directory names. A `Path` can represent a root, a root and a sequence of names, or simply one or more name elements. A `Path` is considered to be an empty path if it consists solely of one name element that is empty or equal to `"."`. Accessing a file using an empty path is equivalent to accessing the default directory of the process.

#
Examples

    Path["foo/bar/baz.cr"].parent    # => Path["foo/bar"]
    Path["foo/bar/baz.cr"].basename  # => "baz.cr"
    Path["./foo/../bar"].normalize   # => Path["bar"]
    Path["~/bin"].expand(home: true) # => Path["/home/crystal/bin"]

For now, its methods are purely lexical, there is no direct filesystem access.

Path handling comes in different kinds depending on operating system:

- `Path.posix()` creates a new POSIX path
- `Path.windows()` creates a new Windows path
- `Path.new()` means `Path.posix` on POSIX platforms and `Path.windows()` on Windows platforms.

    # On POSIX system:
    Path.new("foo", "bar", "baz.cr") == Path.posix("foo/bar/baz.cr")
    # On Windows system:
    Path.new("foo", "bar", "baz.cr") == Path.windows("foo\\bar\\baz.cr")

The main differences between Windows and POSIX paths:

- POSIX paths use forward slash (`#/`) as only path separator, Windows paths use backslash (`\`) as default separator but also recognize forward slashes.
- POSIX paths are generally case-sensitive, Windows paths case-insensitive (see `#<=>`).
- A POSIX path is absolute if it begins with a forward slash (`#/`). A Windows path is absolute if it starts with a drive letter and root (`C:\`).

    Path.posix("/foo/./bar").normalize   # => Path.posix("/foo/bar")
    Path.windows("/foo/./bar").normalize # => Path.windows("\\foo\\bar")

    Path.posix("/foo").absolute?   # => true
    Path.windows("/foo").absolute? # => false

    Path.posix("foo") == Path.posix("FOO")     # => false
    Path.windows("foo") == Path.windows("FOO") # => true

##
Included Modules

- Comparable(Path)

##
Defined in:

json/to_json.cr
path.cr
yaml/to_yaml.cr

##
Constant Summary

SEPARATORS = `separators(Kind.native)`

  The file/directory separator characters of the current platform. `{'/'}` on POSIX, `{'\\', '/'}` on Windows.

##
Constructors

- .[](parts : Enumerable) : Path

  Creates a new `Path` of native kind.

- .[](name : String | Path, *parts) : Path

  Creates a new `Path` of native kind.

- .home : Path

  Returns the path of the home directory of the current user.

- .new(ctx : YAML::ParseContext, node : YAML::Nodes::Node)
- .new(name : String = "") : Path

  Creates a new `Path` of native kind.

- .new(path : Path) : Path

  Creates a new `Path` of native kind.

- .new(parts : Enumerable) : Path

  Creates a new `Path` of native kind.

- .new(pull : JSON::PullParser)
- .new(name : String | Path, *parts : String | Path) : Path

  Creates a new `Path` of native kind.

- .posix(name : String = "") : Path

  Creates a new `Path` of POSIX kind.

- .posix(path : Path) : Path

  Creates a new `Path` of POSIX kind.

- .posix(parts : Enumerable) : Path

  Creates a new `Path` of POSIX kind.

- .posix(name : String | Path, *parts : String | Path) : Path

  Creates a new `Path` of POSIX kind.

- .windows(name : String = "") : Path

  Creates a new `Path` of Windows kind.

- .windows(path : Path) : Path

  Creates a new `Path` of Windows kind.

- .windows(parts : Enumerable) : Path

  Creates a new `Path` of Windows kind.

- .windows(name : String | Path, *parts : String | Path) : Path

  Creates a new `Path` of Windows kind.

##
Instance Method Summary

- #/(part : Path | String) : Path

  Appends the given part to this path and returns the joined path.

- #<=>(other : Path)

  Compares this path to other.

- #==(other : self)

  Returns `true` if this path is considered equivalent to other.

- #absolute? : Bool

  Returns `true` if this path is absolute.

- #anchor : Path | Nil

  Returns the concatenation of `#drive` and `#root`.

- #basename(suffix : String | Nil = nil) : String

  Returns the last component of this path.

- #dirname : String

  Returns all components of this path except the last one.

- #drive : Path | Nil

  Returns a path representing the drive component or `nil` if this path does not contain a drive.

- #drive_and_root : Tuple(String | Nil, String | Nil)

  Returns a tuple of `#drive` and `#root` as strings.

- #each_parent(&block : Path -> )

  Yields each parent of this path beginning with the topmost parent.

- #each_part(& : String -> )

  Yields each component of this path as a `String`.

- #each_part : Iterator(String)

  Returns an iterator over all components of this path.

- #ends_with_separator? : Bool
- #expand(base : Path | String = Dir.current, *, home : Path | String | Bool = false, expand_base = true) : Path

  Converts this path to an absolute path.

- #extension : String

  Returns the extension of this path, or an empty string if it has no extension.

- #hash(hasher)

  See `Object#hash(hasher)`

- #inspect(io : IO)

  Inspects this path to io.

- #join(parts : Enumerable) : Path

  Appends the given parts to this path and returns the joined path.

- #join(part) : Path

  Appends the given part to this path and returns the joined path.

- #join(*parts) : Path

  Appends the given parts to this path and returns the joined path.

- #native? : Bool

  Returns `true` if this is a native path for the target platform.

- #normalize(*, remove_final_separator : Bool = true) : Path

  Removes redundant elements from this path and returns the shortest equivalent path by purely lexical processing.

- #parent : Path

  Returns the parent path of this path.

- #parents : Array(Path)

  Returns all parent paths of this path beginning with the topmost path.

- #parts : Array(String)

  Returns the components of this path as an `Array(String)`.

- #posix? : Bool

  Returns `true` if this is a POSIX path.

- #relative_to(base : Path | String) : Path

  Same as `#relative_to` but returns `self` if `self` can't be expressed as relative path to base.

- #relative_to?(base : Path) : Path | Nil

  Returns a relative path that is lexically equivalent to `self` when joined to base with an intervening separator.

- #relative_to?(base : String) : Path | Nil

  Returns a relative path that is lexically equivalent to `self` when joined to base with an intervening separator.

- #root : Path | Nil

  Returns the root path component of this path or `nil` if it is not rooted.

- #sibling(name : Path | String) : Path

  Resolves path name in this path's parent directory.

- #stem : String

  Returns the last component of this path without the extension.

- #to_json(json : JSON::Builder) : Nil
- #to_json_object_key : String
- #to_kind(kind, *, mappings : Bool = true) : Path

  Converts this path to the given kind.

- #to_native : Path

  Converts this path to a native path.

- #to_posix(*, mappings : Bool = true) : Path

  Converts this path to a POSIX path.

- #to_s(io : IO)

  Appends the string representation of this path to io.

- #to_s : String

  Returns the string representation of this path.

- #to_uri : URI

  Returns a new `URI` with `file` scheme from this path.

- #to_windows(*, mappings : Bool = true) : Path

  Converts this path to a Windows path.

- #to_yaml(yaml : YAML::Nodes::Builder) : Nil
- #windows? : Bool

  Returns `true` if this is a Windows path.

### Instance methods inherited from module `Comparable(Path)`

<(other : T) : Bool <, <=(other : T) <=, <=>(other : T) <=>, ==(other : T) ==, >(other : T) : Bool >, >=(other : T) >=, clamp(min, max)
clamp(range : Range) clamp

### Instance methods inherited from struct `Struct`

==(other) : Bool ==, hash(hasher) hash, inspect(io : IO) : Nil inspect, pretty_print(pp) : Nil pretty_print, to_s(io : IO) : Nil to_s

### Instance methods inherited from struct `Value`

==(other : JSON::Any)
==(other : YAML::Any)
==(other) ==, dup dup

### Instance methods inherited from class `Object`

! : Bool !, !=(other) !=, !~(other) !~, ==(other) ==, ===(other : JSON::Any)
===(other : YAML::Any)
===(other) ===, =~(other) =~, as(type : Class) as, as?(type : Class) as?, class class, dup dup, hash(hasher)
hash hash, in?(collection : Object) : Bool
in?(*values : Object) : Bool in?, inspect(io : IO) : Nil
inspect : String inspect, is_a?(type : Class) : Bool is_a?, itself itself, nil? : Bool nil?, not_nil!(message)
not_nil! not_nil!, pretty_inspect(width = 79, newline = "\n", indent = 0) : String pretty_inspect, pretty_print(pp : PrettyPrint) : Nil pretty_print, responds_to?(name : Symbol) : Bool responds_to?, tap(&) tap, to_json(io : IO) : Nil
to_json : String to_json, to_pretty_json(indent : String = " ") : String
to_pretty_json(io : IO, indent : String = " ") : Nil to_pretty_json, to_s(io : IO) : Nil
to_s : String to_s, to_yaml(io : IO) : Nil
to_yaml : String to_yaml, try(&) try, unsafe_as(type : T.class) forall T unsafe_as

### Class methods inherited from class `Object`

from_json(string_or_io, root : String)
from_json(string_or_io) from_json, from_yaml(string_or_io : String | IO) from_yaml

### Macros inherited from class `Object`

class_getter(*names, &block) class_getter, class_getter!(*names) class_getter!, class_getter?(*names, &block) class_getter?, class_property(*names, &block) class_property, class_property!(*names) class_property!, class_property?(*names, &block) class_property?, class_setter(*names) class_setter, def_clone def_clone, def_equals(*fields) def_equals, def_equals_and_hash(*fields) def_equals_and_hash, def_hash(*fields) def_hash, delegate(*methods, to object) delegate, forward_missing_to(delegate) forward_missing_to, getter(*names, &block) getter, getter!(*names) getter!, getter?(*names, &block) getter?, property(*names, &block) property, property!(*names) property!, property?(*names, &block) property?, setter(*names) setter

##
Constructor Detail

def self.[](parts : Enumerable) : Path #

Creates a new `Path` of native kind.

When compiling for a windows target, this is equal to `Path.windows()`, otherwise `Path.posix` is used.

def self.[](name : String | Path, *parts) : Path #

Creates a new `Path` of native kind.

When compiling for a windows target, this is equal to `Path.windows()`, otherwise `Path.posix` is used.

def self.home : Path #

Returns the path of the home directory of the current user.

def self.new(ctx : YAML::ParseContext, node : YAML::Nodes::Node) #
def self.new(name : String = "") : Path #

Creates a new `Path` of native kind.

When compiling for a windows target, this is equal to `Path.windows()`, otherwise `Path.posix` is used.

def self.new(path : Path) : Path #

Creates a new `Path` of native kind.

When compiling for a windows target, this is equal to `Path.windows()`, otherwise `Path.posix` is used.

def self.new(parts : Enumerable) : Path #

Creates a new `Path` of native kind.

When compiling for a windows target, this is equal to `Path.windows()`, otherwise `Path.posix` is used.

def self.new(pull : JSON::PullParser) #
def self.new(name : String | Path, *parts : String | Path) : Path #

Creates a new `Path` of native kind.

When compiling for a windows target, this is equal to `Path.windows()`, otherwise `Path.posix` is used.

def self.posix(name : String = "") : Path #

Creates a new `Path` of POSIX kind.

def self.posix(path : Path) : Path #

Creates a new `Path` of POSIX kind.

def self.posix(parts : Enumerable) : Path #

Creates a new `Path` of POSIX kind.

def self.posix(name : String | Path, *parts : String | Path) : Path #

Creates a new `Path` of POSIX kind.

def self.windows(name : String = "") : Path #

Creates a new `Path` of Windows kind.

def self.windows(path : Path) : Path #

Creates a new `Path` of Windows kind.

def self.windows(parts : Enumerable) : Path #

Creates a new `Path` of Windows kind.

def self.windows(name : String | Path, *parts : String | Path) : Path #

Creates a new `Path` of Windows kind.

##
Instance Method Detail

def /(part : Path | String) : Path #

Appends the given part to this path and returns the joined path.

    Path["foo"] / "bar" / "baz"     # => Path["foo/bar/baz"]
    Path["foo/"] / Path["/bar/baz"] # => Path["foo/bar/baz"]

See `#join(part)` for details.

def <=>(other : Path) #

Compares this path to other.

The comparison is performed strictly lexically: `foo` and `./foo` are not treated as equal. Nor are paths of different `kind`. To compare paths semantically, they need to be normalized and converted to the same kind.

    Path["foo"] <=> Path["foo"]               # => 0
    Path["foo"] <=> Path["./foo"]             # => 1
    Path["foo"] <=> Path["foo/"]              # => -1
    Path.posix("foo") <=> Path.windows("foo") # => -1

Comparison is case-sensitive for POSIX paths and case-insensitive for Windows paths.

    Path.posix("foo") <=> Path.posix("FOO")     # => 1
    Path.windows("foo") <=> Path.windows("FOO") # => 0

def ==(other : self) #

Returns `true` if this path is considered equivalent to other.

The comparison is performed strictly lexically: `foo` and `./foo` are not treated as equal. Nor are paths of different `kind`. To compare paths semantically, they need to be normalized and converted to the same kind.

    Path["foo"] == Path["foo"]               # => true
    Path["foo"] == Path["./foo"]             # => false
    Path["foo"] == Path["foo/"]              # => false
    Path.posix("foo") == Path.windows("foo") # => false

Comparison is case-sensitive for POSIX paths and case-insensitive for Windows paths.

    Path.posix("foo") == Path.posix("FOO")     # => false
    Path.windows("foo") == Path.windows("FOO") # => true

def absolute? : Bool #

Returns `true` if this path is absolute.

A POSIX path is absolute if it begins with a forward slash (`#/`). A Windows path is absolute if it begins with a drive letter and root (`C:\`) or with a UNC share (`\\server\share\`).

def anchor : Path | Nil #

Returns the concatenation of `#drive` and `#root`.

    Path["/etc/"].anchor                           # => Path["/"]
    Path.windows("C:Program Files").anchor         # => Path.windows("C:")
    Path.windows("C:\\Program Files").anchor       # => Path.windows("C:\\")
    Path.windows("\\\\host\\share\\folder").anchor # => Path.windows("\\\\host\\share\\")

def basename(suffix : String | Nil = nil) : String #

Returns the last component of this path.

If suffix is given, it is stripped from the end.

In case the last component is the empty string (i.e. the path has a trailing separator), the second to last component is returned. For a path that only consists of an anchor, or an empty path, the base name is equivalent to the full path.

    Path["/foo/bar/file.cr"].basename # => "file.cr"
    Path["/foo/bar/"].basename        # => "bar"
    Path["/foo/bar/."].basename       # => "."
    Path["/"].basename                # => "/"
    Path[""].basename                 # => ""

def dirname : String #

Returns all components of this path except the last one.

    Path["/foo/bar/file.cr"].dirname # => "/foo/bar"

def drive : Path | Nil #

Returns a path representing the drive component or `nil` if this path does not contain a drive.

See `#anchor` for the combination of drive and `#root`.

    Path.windows("C:\\Program Files").drive       # => Path.windows("C:")
    Path.windows("\\\\host\\share\\folder").drive # => Path.windows("\\\\host\\share")

NOTE Drives are only available for Windows paths. It can either be a drive letter (`C:`) or a UNC share (`\\host\share`).

def drive_and_root : Tuple(String | Nil, String | Nil) #

Returns a tuple of `#drive` and `#root` as strings.

def each_parent(&block : Path -> ) #

Yields each parent of this path beginning with the topmost parent.

    Path["foo/bar/file.cr"].each_parent { |parent| puts parent }
    # Path["."]
    # Path["foo"]
    # Path["foo/bar"]

def each_part(& : String -> ) #

Yields each component of this path as a `String`.

    Path.new("foo/bar/").each_part # yields: "foo", "bar"

See `#parts` for more examples.

def each_part : Iterator(String) #

Returns an iterator over all components of this path.

    parts = Path.new("foo/bar/").each_part
    parts.next # => "foo"
    parts.next # => "bar"
    parts.next # => Iterator::Stop::INSTANCE

See `#parts` for more examples.

def ends_with_separator? : Bool #
def expand(base : Path | String = Dir.current, *, home : Path | String | Bool = false, expand_base = true) : Path #

Converts this path to an absolute path. Relative paths are referenced from the current working directory of the process (`Dir.current`) unless base is given, in which case it will be used as the reference path.

    Path["foo"].expand                 # => Path["/current/path/foo"]
    Path["~/foo"].expand(home: "/bar") # => Path["/bar/foo"]
    Path["baz"].expand("/foo/bar")     # => Path["/foo/bar/baz"]

home specifies the home directory which `~` will expand to. "~" is expanded to the value passed to home. If it is `false` (default), home is not expanded. If `true`, it is expanded to the user's home directory (`Path.home`).

If expand_base is `true`, base itself will be expanded in `Dir.current` if it is not an absolute path. This guarantees the method returns an absolute path (assuming that `Dir.current` is absolute).

def extension : String #

Returns the extension of this path, or an empty string if it has no extension.

    Path["foo.cr"].extension     # => ".cr"
    Path["foo"].extension        # => ""
    Path["foo.tar.gz"].extension # => ".gz"

def hash(hasher) #
Description copied from struct Struct

See `Object#hash(hasher)`

def inspect(io : IO) #

Inspects this path to io.

def join(parts : Enumerable) : Path #

Appends the given parts to this path and returns the joined path.

    Path["foo"].join("bar", "baz")           # => Path["foo/bar/baz"]
    Path["foo/"].join(Path["/bar/", "/baz"]) # => Path["foo/bar/baz"]
    Path["/foo/"].join("/bar/", "/baz/")     # => Path["/foo/bar/baz/"]

Non-matching paths are implicitly converted to this path's kind.

    Path.posix("foo/bar").join(Path.windows("baz\\baq")) # => Path.posix("foo/bar/baz/baq")
    Path.windows("foo\\bar").join(Path.posix("baz/baq")) # => Path.windows("foo\\bar\\baz/baq")

See `#join(part)` for details.

def join(part) : Path #

Appends the given part to this path and returns the joined path.

    Path["foo"].join("bar")     # => Path["foo/bar"]
    Path["foo/"].join("/bar")   # => Path["foo/bar"]
    Path["/foo/"].join("/bar/") # => Path["/foo/bar/"]

Joining an empty string (`""`) appends a trailing path separator. In case the path already ends with a trailing separator, no additional separator is added.

    Path["a/b"].join("")   # => Path["a/b/"]
    Path["a/b/"].join("")  # => Path["a/b/"]
    Path["a/b/"].join("c") # => Path["a/b/c"]

def join(*parts) : Path #

Appends the given parts to this path and returns the joined path.

    Path["foo"].join("bar", "baz")       # => Path["foo/bar/baz"]
    Path["foo/"].join("/bar/", "/baz")   # => Path["foo/bar/baz"]
    Path["/foo/"].join("/bar/", "/baz/") # => Path["/foo/bar/baz/"]

See `#join(part)` for details.

def native? : Bool #

Returns `true` if this is a native path for the target platform.

def normalize(*, remove_final_separator : Bool = true) : Path #

Removes redundant elements from this path and returns the shortest equivalent path by purely lexical processing. It applies the following rules iteratively until no further processing can be done:

1. Replace multiple slashes with a single slash.
2. Eliminate each `.` path name element (the current directory).
3. Eliminate each `..` path name element (the parent directory) preceded by a non-`..` element along with the latter.
4. Eliminate `..` elements that begin a rooted path: that is, replace `"/.."` by `"/"` at the beginning of a path.

If the path turns to be empty, the current directory (`"."`) is returned.

The returned path ends in a slash only if it is the root (`"/"`, `\`, or `C:\`).

See also Rob Pike: Lexical File Names in Plan 9 or Getting Dot-Dot Right

def parent : Path #

Returns the parent path of this path.

If the path is empty, it returns `"."`. If the path is rooted and in the top-most hierarchy, the root path is returned.

    Path["foo/bar/file.cr"].parent # => Path["foo/bar"]
    Path["foo"].parent             # => Path["."]
    Path["/foo"].parent            # => Path["/"]
    Path["/"].parent               # => Path["/"]
    Path[""].parent                # => Path["."]
    Path["foo/bar/."].parent       # => Path["foo/bar"]

def parents : Array(Path) #

Returns all parent paths of this path beginning with the topmost path.

    Path["foo/bar/file.cr"].parents # => [Path["."], Path["foo"], Path["foo/bar"]]

def parts : Array(String) #

Returns the components of this path as an `Array(String)`.

    Path.new("foo/bar/").parts                   # => ["foo", "bar"]
    Path.new("/Users/foo/bar.cr").parts          # => ["/", "Users", "foo", "bar.cr"]
    Path.windows("C:\\Users\\foo\\bar.cr").parts # => ["C:\\", "Users", "foo", "bar.cr"]
    Path.posix("C:\\Users\\foo\\bar.cr").parts   # => ["C:\\Users\\foo\\bar.cr"]

def posix? : Bool #

Returns `true` if this is a POSIX path.

def relative_to(base : Path | String) : Path #

Same as `#relative_to` but returns `self` if `self` can't be expressed as relative path to base.

def relative_to?(base : Path) : Path | Nil #

Returns a relative path that is lexically equivalent to `self` when joined to base with an intervening separator.

The returned path is in normalized form.

That means with normalized paths `base.join(target.relative_to(base))` is equivalent to `target`.

Returns `nil` if `self` cannot be expressed as relative to base or if knowing the current working directory would be necessary to resolve it. The latter can be avoided by expanding the paths first.

def relative_to?(base : String) : Path | Nil #

Returns a relative path that is lexically equivalent to `self` when joined to base with an intervening separator.

The returned path is in normalized form.

That means with normalized paths `base.join(target.relative_to(base))` is equivalent to `target`.

Returns `nil` if `self` cannot be expressed as relative to base or if knowing the current working directory would be necessary to resolve it. The latter can be avoided by expanding the paths first.

def root : Path | Nil #

Returns the root path component of this path or `nil` if it is not rooted.

See `#anchor` for the combination of `#drive` and root.

    Path["/etc/"].root                           # => Path["/"]
    Path.windows("C:Program Files").root         # => nil
    Path.windows("C:\\Program Files").root       # => Path.windows("\\")
    Path.windows("\\\\host\\share\\folder").root # => Path.windows("\\")

def sibling(name : Path | String) : Path #

Resolves path name in this path's parent directory.

Raises `Path::Error` if `#parent` is `nil`.

def stem : String #

Returns the last component of this path without the extension.

This is equivalent to `self.basename(self.extension)`.

    Path["file.cr"].stem     # => "file"
    Path["file.tar.gz"].stem # => "file.tar"
    Path["foo/file.cr"].stem # => "file"

def to_json(json : JSON::Builder) : Nil #
def to_json_object_key : String #
def to_kind(kind, *, mappings : Bool = true) : Path #

Converts this path to the given kind.

See `#to_windows` and `#to_posix` for details.

- `#to_native` converts to the native path semantics.

def to_native : Path #

Converts this path to a native path.

- `#to_kind` performs a configurable conversion.

def to_posix(*, mappings : Bool = true) : Path #

Converts this path to a POSIX path.

It returns a new instance with `Kind::POSIX` and all occurrences of Windows' backslash file separators (`\\`) replaced by forward slash (`#/`). If `#posix?` is true, this is a no-op.

    Path.windows("foo/bar\\baz").to_posix # => Path.posix("foo/bar/baz")
    Path.posix("foo/bar\\baz").to_posix   # => Path.posix("foo/bar\\baz")

When mappings is `true` (default), replacements for forbidden characters in Windows paths are substituted by the original characters when converting to a POSIX path. Originals are calculated by subtracting `0xF000` from the replacement codepoint. For example, the `U+F05C` becomes `U+005C`, the backslash character.

    Path.windows("foo\uF05Cbar").to_posix(mappings: true)  # => Path.posix("foo\\bar")
    Path.windows("foo\uF05Cbar").to_posix(mappings: false) # => Path.posix("foo\uF05Cbar")

- `#to_windows` performs the inverse conversion.
- `#to_kind` performs a configurable conversion.

def to_s(io : IO) #

Appends the string representation of this path to io.

def to_s : String #

Returns the string representation of this path.

def to_uri : URI #

Returns a new `URI` with `file` scheme from this path.

A URI can only be created with an absolute path. Raises `Path::Error` if this path is not absolute.

def to_windows(*, mappings : Bool = true) : Path #

Converts this path to a Windows path.

This creates a new instance with the same string representation but with `Kind::WINDOWS`. If `#windows?` is true, this is a no-op.

    Path.posix("foo/bar").to_windows   # => Path.windows("foo/bar")
    Path.windows("foo/bar").to_windows # => Path.windows("foo/bar")

When mappings is `true` (default), forbidden characters in Windows paths are substituted by replacement characters when converting from a POSIX path. Replacements are calculated by adding `0xF000` to their codepoint. For example, the backslash character `U+005C` becomes `U+F05C`.

    Path.posix("foo\\bar").to_windows(mappings: true)  # => Path.windows("foo\uF05Cbar")
    Path.posix("foo\\bar").to_windows(mappings: false) # => Path.windows("foo\\bar")

- `#to_posix` performs the inverse conversion.
- `#to_kind` performs a configurable conversion.

def to_yaml(yaml : YAML::Nodes::Builder) : Nil #
def windows? : Bool #

Returns `true` if this is a Windows path.