module Fpath:sig
..end
A (file system) path specifies a file or a directory in a file system hierarchy. A path has three parts:
Fpath.dir_sep
whose presence
distinguishes absolute paths ("/a"
) from relative
ones ("a"
)Fpath.dir_sep
separated segments. Segments are
non empty strings except for maybe the last one. The latter
distinguishes directory paths
("a/b/"
) from file paths ("a/b"
).
The path segments "."
and ".."
are relative
path segments that respectively denote the current and parent
directory. The basename of a path is its last
non-empty segment if it is not a relative path segment or the empty
string otherwise.
Consult a few important tips.
Note. Fpath
processes paths without accessing the file system.
v0.7.2 - homepage
val dir_sep : string
dir_sep
is the platform dependent natural directory separator. This is
"/"
on POSIX and "\\"
on Windows.val is_seg : string -> bool
val is_rel_seg : string -> bool
is_rel_seg s
is true iff s
is a relative segment, that is
"."
or ".."
.type
t
val v : string -> t
v s
is the string s
as a path.Invalid_argument
if s
is not a valid path. Use
Fpath.of_string
to deal with untrusted input.val add_seg : t -> string -> t
add_seg p seg
adds segment seg
to the segments of p
if
p
's last segment is non-empty or replaces the last empty
segment with seg
. Examples.Invalid_argument
if Fpath.is_seg
seg
is false
.val (/) : t -> string -> t
val append : t -> t -> t
append p q
appends q
to p
as follows:
q
is absolute or has a non-empty volume then
q
is returned.q
's segments to p
using Fpath.add_seg
.val (//) : t -> t -> t
val split_volume : t -> string * t
split_volume p
is the pair (vol, q)
where vol
is
the platform dependent volume of p
or the empty string
if there is none and q
the path p
without its volume, that is
its optional root Fpath.dir_sep
and segments.
On POSIX if vol
is non-empty then it
can only be "/"
(e.g. in v "//a/b"
). On Windows vol
may be
one of the following prefixes parsed before an
absolute root Fpath.dir_sep
, except in the first case
where a relative path can follow:
$(drive):
\\$(server)\$(share)
\\?\$(drive):
\\?\$(server)\$(share)
\\?\UNC\$(server)\$(share)
\\.\$(device)
The following invariant holds:
equal p (v @@ vol ^ (to_string q))
val segs : t -> string list
segs p
is p
's non-empty list of segments. Absolute paths have an
initial empty string added, this allows to recover the path's string with
String.concat
~sep:dir_sep
. Examples.
The following invariant holds:
equal p (v @@ (fst @@ split_volume p) ^ (String.concat ~sep:dir_sep
(segs p)))
Note. The following functions use syntactic semantic properties
of paths. Given a path, these properties can be different from the one
your file system attributes to it.
val is_dir_path : t -> bool
is_dir_path p
is true
iff p
represents a directory. This
means that p
's last segment is either empty (""
) or
relative. The property is invariant with respect
to normalization. Examples.val is_file_path : t -> bool
is_file_path p
is true
iff p
represents a file. This is the
negation of Fpath.is_dir_path
. This means that p
's last segment is
neither empty (""
) nor relative. The property is
invariant with respect to normalization.
Examples.val to_dir_path : t -> t
to_dir_path p
is Fpath.add_seg
p ""
. It ensure that the result
represents a directory and, if converted to a
string, that it ends with a Fpath.dir_sep
.
Examples.val filename : t -> string
filename p
is the file name of p
. This is the last segment of
p
if p
is a file path and the empty string
otherwise. The result is invariant with respect to
normalization. See also
Fpath.basename
. Examples.val split_base : t -> t * t
split_base p
splits p
into a directory d
and a relative
base path b
such that:
b
is a relative path that contains the segments of p
that start at the last non-empty segment. This means
that b
has a single non-empty segment, and preserves
directoryness of p
. If p
is a
root path there are no such segments and b
is "./"
.d
is a directory such that d // b
represents the same path as p
. They may however differ
syntactically when converted to a string.
Note. Normalizing p
before using the function
ensures that b
is a relative segment iff p
cannot
be named (like in "."
, "../../"
, "/"
, etc.).
val base : t -> t
base p
is snd (split_base p)
.val basename : t -> string
basename p
is p
's last non-empty segment if non-relative or
the empty string otherwise. The latter occurs only on root
paths and on paths whose last non-empty segment is a
relative segment. See also Fpath.filename
and
Fpath.base
. Examples.
Note. Normalizing p
before using the function
ensures the empty string is only returned iff p
cannot be
named (like in "."
, "../../"
, "/"
, etc.)
val parent : t -> t
parent p
is a directory path that contains p
.
If p
is a root path this is p
itself.
Examples.
Warning. parent p // base p
may not represent p
, use
Fpath.split_base
for this.
val rem_empty_seg : t -> t
rem_empty_seg p
removes an existing last empty segment of p
if p
is not a root path. This ensure that if p
is
converted to a string it will not have a trailing Fpath.dir_sep
unless p
is a root path. Note that this may affect p
's
directoryness. Examples.val normalize : t -> t
normalize p
is a path that represents the same path as p
,
directoryness included, and that has the following
properties:
p
is absolute the resulting path has no "."
and ".."
segments.p
is relative the resulting path is either "./"
or
it has no "."
segments and ".."
segments may only appear as
initial segments.p
is a directory it always end with
an empty segment; this means it doesn't end with "."
or ".."
.
Warning. Like file and directory path functions
this function does not consult the file system and is purely
based on the syntactic semantic of paths which can be different
from the one of your concrete file system attributes. For example in
presence of symbolic links the resulting path may not point to the same
entity. Use the normalization functions of your OS system library to
ensure correct behaviour with respect to a concrete file system.
Warning. The syntactic prefix relation between paths does not, in general, entail directory containement. The following examples show this:
is_prefix (v "..") (v "../..") = true
is_prefix (v "..") (v ".") = false
However, on normalized, absolute paths,
the prefix relation does entail directory containement. See also
Fpath.is_rooted
.val is_prefix : t -> t -> bool
is_prefix prefix p
is true
if prefix
is a prefix of
p
. This checks that:
prefix
has the same optional volume as p
.prefix
has the same optional root directory separator as p
.prefix
is a prefix of those of
p
, ignoring the last empty segment of prefix
if the number of
non-empty segments of p
is strictly larger than those of prefix
.
This means that is_prefix (v "a/") (v "a/b")
is true
but
is_prefix (v "a/") (v "a")
is false
val find_prefix : t -> t -> t option
find_prefix p p'
is Some prefix
if there exists prefix
such
that prefix
is the longest path with is_prefix prefix p &&
is_prefix prefix p' = true
and None
otherwise. Note that if
both p
and p'
are absolute and have the same volume then a
prefix always exists: the root path of their volume.
Examples.val rem_prefix : t -> t -> t option
rem_prefix prefix p
is:
None
if prefix
is not a prefix of p
or if prefix
and p
are equal.Some q
otherwise where q
is p
without the
prefix prefix
and preserves p
's
directoryness. This means that q
is a always
relative and that the path prefix // q
and p
represent the
same paths. They may however differ syntactically when
converted to a string.val relativize : root:t -> t -> t option
relativize ~root p
is:
Some q
if there exists a relative path q
such
that root // q
and p
represent the same paths,
directoryness included. They may however differ
syntactically when converted to a string. Note that q
is
normalized.None
otherwise.val is_rooted : root:t -> t -> bool
is_rooted root p
is true
iff the path p
is the
directory root
or contained in root
and that p
can be relativized w.r.t. root
(the normalized relative
path will have no parent directory segments).
Examples.val is_rel : t -> bool
is_rel p
is true
iff p
is a relative path, i.e. the root
directory separator is missing in p
.val is_abs : t -> bool
is_abs p
is true
iff p
is an absolute path, i.e. the root
directory separator is present in p
.val is_root : t -> bool
is_root p
is true
iff p
is a root directory, i.e. p
has the
root directory separator and a single, empty, segment.
Examples.
Warning. By definition this is a syntactic test. For example it will
return false
on "/a/.."
or "/.."
. Normalizing
the path before testing avoids this problem.
val is_current_dir : ?prefix:bool -> t -> bool
is_current_dir p
is true iff p
is the current relative directory,
i.e. either "."
or "./"
. If prefix
is true
(defaults to false
)
simply checks that p
is relative and its first segment
is "."
.
Warning. By definition this is a syntactic test. For example it will
return false
on "./a/.."
or "./."
. Normalizing the
path before testing avoids this problem.
val is_parent_dir : ?prefix:bool -> t -> bool
is_parent_dir p
is true
iff p
is the relative parent directory,
i.e. either ".."
or "../"
. If prefix
is true
(defaults to false
),
simply checks that p
is relative and its first segment
is ".."
.
Warning. By definition this is a syntactic test. For example it will
return false
on "./a/../.."
or "./.."
. Normalizing the
path before testing avoids this problem.
val is_dotfile : t -> bool
is_dotfile p
is true
iff p
's basename is non
empty and starts with a '.'
.
Warning. By definition this is a syntactic test. For example it will
return false
on ".ssh/."
. Normalizing the
path before testing avoids this problem.
val equal : t -> t -> bool
equal p p'
is true
if p
and p'
have the same volume
are both relative or absolute and have the same segments.
Warning. By definition this is a syntactic test. For example
equal (v "./") (v "a/..")
is false
. Normalizing
the paths before testing avoids this problem.
val compare : t -> t -> int
val to_string : t -> string
val of_string : string -> (t, [ `Msg of string ]) Result.result
of_string s
is the string s
as a path. The following transformations
are performed on the string:
'/'
occurence is converted to '\\'
before
any processing occurs."a//b"
becomes "a/b"
, "//a////b//"
becomes "//a/b/"
, etc."\\\\server\\share"
becomes
"\\\\server\\share\\"
,
but incomplete UNC volumes like "\\\\a"
return Result.Error
.
Result.Error (`Msg (strf "%S: invalid path" s))
is returned if
s
or the path following the volume is empty (""
),
except on Windows UNC paths, see above.s
has null byte ('\x00'
).s
is an invalid UNC path (e.g. "\\\\"
or "\\\\a"
)val pp : Format.formatter -> t -> unit
val dump : Format.formatter -> t -> unit
dump ppf p
prints path p
on ppf
using String.dump
.
The file extension (resp. multiple file extension) of a
path segment is the suffix that starts at the last (resp. first)
occurence of a '.'
that is preceeded by at least one non '.'
character. If there is no such occurence in the segment, the
extension is empty. With these definitions, "."
, ".."
,
"..."
and dot files like ".ocamlinit"
or "..ocamlinit"
have
no extension, but ".emacs.d"
and "..emacs.d"
do have one.
Warning. The following functions act on paths whose
basename is non empty and do nothing otherwise.
Normalizing p
before using the functions ensures
that the functions do nothing iff p
cannot be named, see
Fpath.basename
.
typeext =
string
val get_ext : ?multi:bool -> t -> ext
get_ext p
is p
's basename file extension or the
empty string if there is no extension. If multi
is true
(defaults to false
), returns the multiple file
extension. Examples.val has_ext : ext -> t -> bool
has_ext e p
is true
iff get_ext p = e || get_ext ~multi:true p = e
.
If e
doesn't start with a '.'
one is prefixed before making
the test. Examples.val mem_ext : ext list -> t -> bool
mem_ext exts p
is
List.mem (get_ext p) exts || List.mem (get_ext ~multi:true p) exts
.val exists_ext : ?multi:bool -> t -> bool
exists_ext ~multi p
is true
iff p
's basename
file extension is not empty. If multi
is true
(default to
false
) returns true
iff p
has more than one extension.
Examples.val add_ext : ext -> t -> t
add_ext ext p
is p
with the string ext
concatenated to p
's
basename, if non empty. If ext
doesn't start with a '.'
one is prefixed to it before concatenation except if ext
is
""
. Examples.Invalid_argument
if Fpath.is_seg
ext
is false
.val rem_ext : ?multi:bool -> t -> t
rem_ext p
is p
with the extension of p
's
basename removed. If multi
is true
(default to
false
), the multiple file extension is
removed. Examples.val set_ext : ?multi:bool -> ext -> t -> t
set_ext ?multi ext p
is add_ext ext (rem_ext ?multi p)
.val split_ext : ?multi:bool -> t -> t * ext
split_ext ?multi p
is (rem_ext ?multi p, get_ext ?multi p)
. If this is
(q, ext)
the following invariant holds:
equal p (add_ext q ext)
val (+) : t -> ext -> t
p + ext
is add_ext ext p
. Left associative.val (-+) : t -> ext -> t
p -+ ext
is set_ext ext p
. Left associative.typepath =
t
type
set
Fpath.equal
.module Set:sig
..end
type +'a
map
module Map:sig
..end
"a"
) or a
directory path (e.g. "a/"
).'\\'
and '/'
as directory separator.
However Fpath
on Windows converts '/'
to '\\'
on the
fly. Therefore you should either use '/'
for defining
constant paths you inject with Fpath.v
or better, construct them
directly with Fpath.(/)
. Fpath.to_string
then converts paths to strings
using the platform's specific directory separator Fpath.dir_sep
."/"
. On Windows each volume can have a root path.
Use Fpath.is_root
on normalized paths to detect roots.Fpath.to_string
to construct URIs, Fpath.to_string
uses
Fpath.dir_sep
to separate segments, on Windows this is '\\'
which
is not what URIs expect. Access path segments directly
with Fpath.segs
; note that you will need to percent encode these.
Fpath.add_seg
equal (add_seg (v "/a") "b") (v "/a/b")
equal (add_seg (v "/a/") "b") (v "/a/b")
equal (add_seg (v "/a/b") "") (v "/a/b/")
equal (add_seg (v "/a/b/") "") (v "/a/b/")
equal (add_seg (v "/") "") (v "/")
equal (add_seg (v "/") "a") (v "/a")
equal (add_seg (v ".") "") (v "./")
equal (add_seg (v ".") "a") (v "./a")
equal (add_seg (v "..") "") (v "../")
equal (add_seg (v "..") "a") (v "../a")
Fpath.append
equal (append (v "/a/b/") (v "e/f")) (v "/a/b/e/f")
equal (append (v "/a/b") (v "e/f")) (v "/a/b/e/f")
equal (append (v "/a/b/") (v "/e/f")) (v "/e/f")
equal (append (v "a/b/") (v "e/f")) (v "a/b/e/f")
equal (append (v "a/b") (v "C:e")) (v "C:e")
(Windows)
Fpath.segs
segs (v "/a/b/") = [""; "a"; "b"; ""]
segs (v "/a/b") = [""; "a"; "b"]
segs (v "a/b/") = ["a"; "b"; ""]
segs (v "a/b") = ["a"; "b"]
segs (v "a") = ["a"]
segs (v "/") = [""; ""]
segs (v "\\\\.\\dev\\") = ["";""]
(Windows)segs (v "\\\\server\\share\\a") = ["";"a"]
(Windows)segs (v "C:a") = ["a"]
(Windows)segs (v "C:\\a") = ["";"a"]
(Windows)
Fpath.is_dir_path
is_dir_path (v ".") = true
is_dir_path (v "..") = true
is_dir_path (v "../") = true
is_dir_path (v "/") = true
is_dir_path (v "/a/b/") = true
is_dir_path (v "/a/b") = false
is_dir_path (v "a/") = true
is_dir_path (v "a") = false
is_dir_path (v "a/.") = true
is_dir_path (v "a/..") = true
is_dir_path (v "a/..b") = false
is_dir_path (v "C:\\") = true
(Windows)is_dir_path (v "C:a") = false
(Windows)
Fpath.is_file_path
is_file_path (v ".") = false
is_file_path (v "..") = false
is_file_path (v "../") = false
is_file_path (v "/") = false
is_file_path (v "/a/b/") = false
is_file_path (v "/a/b") = true
is_file_path (v "a/") = false
is_file_path (v "a") = true
is_file_path (v "a/.") = false
is_file_path (v "a/..") = false
is_file_path (v "a/..b") = true
is_file_path (v "C:\\") = false
(Windows)is_file_path (v "C:a") = true
(Windows)
Fpath.to_dir_path
equal (to_dir_path @@ v ".") (v "./")
equal (to_dir_path @@ v "..") (v "../")
equal (to_dir_path @@ v "../") (v "../")
equal (to_dir_path @@ v "/") (v "/")
equal (to_dir_path @@ v "/a/b/") (v "/a/b/")
equal (to_dir_path @@ v "/a/b") (v "/a/b/")
equal (to_dir_path @@ v "a/") (v "a/")
equal (to_dir_path @@ v "a") (v "a/")
equal (to_dir_path @@ v "a/.") (v "a/./")
equal (to_dir_path @@ v "a/..") (v "a/../")
equal (to_dir_path @@ v "a/..b") (v "a/..b/")
equal (to_dir_path @@ v "\\\\server\\share\\")
(v "\\\\server\\share\\")
(Windows)equal (to_dir_path @@ v "C:a") (v "C:a\\")
(Windows)equal (to_dir_path @@ v "C:\\") (v "C:\\")
(Windows)
Fpath.filename
filename (v ".") = ""
filename (v "./") = ""
filename (v "..") = ""
filename (v "../") = ""
filename (v "../..") = ""
filename (v "/") = ""
filename (v "/a/b/") = ""
filename (v "/a/b") = "b"
filename (v "a/") = ""
filename (v "a") = "a"
filename (v "a/.") = ""
filename (v "a/..") = ""
filename (v "a/..b") = "..b"
filename (v "C:\\") = ""
(Windows)filename (v "C:a") = "a"
(Windows)
Fpath.split_base
(split_base @@ v ".") = (v "./"), (v ".")
(split_base @@ v "./") = (v "./"), (v "./")
(split_base @@ v "..") = (v "./"), (v "..")
(split_base @@ v "../") = (v "./"), (v "../")
(split_base @@ v "../../") = (v "../"), (v "../")
(split_base @@ v ".././") = (v "../"), (v "./")
(split_base @@ v "../../../") = (v "../../"), (v "../")
(split_base @@ v "/") = (v "/"), (v "./")
(split_base @@ v "/a/b/") = (v "/a/"), (v "b/")
(split_base @@ v "/a/b") = (v "/a/"), (v "b")
(split_base @@ v "a/") = (v "./"), (v "a/")
(split_base @@ v "a") = (v "./"), (v "a")
(split_base @@ v "a/b") = (v "a/"), (v "b")
(split_base @@ v "a/b/") = (v "a/b/"), (v "b/")
(split_base @@ v "a/.") = (v "a/"), (v ".")
(split_base @@ v "a/..") = (v "a/"), (v "..")
(split_base @@ v "a/../..") = (v "a/../"), (v "..")
(split_base @@ v "a/..b") = (v "a/"), (v "..b")
(split_base @@ v "./a") = (v "./"), (v "a")
(split_base @@ v "./a/") = (v "./"), (v "a/")
(split_base @@ v "../a") = (v "../"), (v "a")
(split_base @@ v "../a/") = (v "../"), (v "a/")
Fpath.basename
basename (v ".") = ""
basename (v "..") = ""
basename (v "../") = ""
basename (v "../../") = ""
basename (v "/") = ""
basename (v "/a/b/") = "b"
basename (v "/a/b") = "b"
basename (v "a/") = "a"
basename (v "a") = "a"
basename (v "a/.") = ""
basename (v "a/./") = ""
basename (v "a/..") = ""
basename (v "a/..b") = "..b"
basename (v "./a") = "a"
basename (v "../a") = "a"
basename (v "C:\\") = ""
(Windows)basename (v "C:a") = "a"
(Windows)
Fpath.parent
equal (parent @@ v ".") (v "./../")
equal (parent @@ v "..") (v "../../")
equal (parent @@ v "../") (v "../../")
equal (parent @@ v "../../") (v "../../../")
equal (parent @@ v "/") (v "/")
equal (parent @@ v "/a/b/") (v "/a/")
equal (parent @@ v "/a/b") (v "/a/")
equal (parent @@ v "a/") (v "./")
equal (parent @@ v "a") (v "./")
equal (parent @@ v "a/.") (v "a/./../")
equal (parent @@ v "a/./") (v "a/./../")
equal (parent @@ v "a/..") (v "a/../../")
equal (parent @@ v "a/../") (v "a/../../")
equal (parent @@ v "a/..b") (v "a/")
equal (parent @@ v "./a") (v "./")
equal (parent @@ v "../a") (v "../")
equal (parent @@ v "../../a") (v "../../")
equal (parent @@ v "\\\\server\\share\\") (v "\\\\server\\share\\")
(Windows)equal (parent @@ v "C:\\") (v "C:\\")
(Windows)equal (parent @@ v "C:a") (v "C:.\\")
(Windows)
Fpath.rem_empty_seg
equal (rem_empty_seg @@ v ".") (v ".")
equal (rem_empty_seg @@ v "..") (v "..")
equal (rem_empty_seg @@ v "../") (v "..")
equal (rem_empty_seg @@ v "../../") (v "../..")
equal (rem_empty_seg @@ v "/") (v "/")
equal (rem_empty_seg @@ v "/a/b/") (v "/a/b")
equal (rem_empty_seg @@ v "/a/b") (v "/a/b")
equal (rem_empty_seg @@ v "a/") (v "a")
equal (rem_empty_seg @@ v "a") (v "a")
equal (rem_empty_seg @@ v "a/.") (v "a/.")
equal (rem_empty_seg @@ v "a/./") (v "a/.")
equal (rem_empty_seg @@ v "a/..") (v "a/..")
equal (rem_empty_seg @@ v "a/../") (v "a/..")
equal (rem_empty_seg @@ v "a/..b") (v "a/..b")
equal (rem_empty_seg @@ v "./a") (v "./a")
equal (rem_empty_seg @@ v "../a") (v "../a")
equal (rem_empty_seg @@ v "../../a") (v "../../a")
equal (rem_empty_seg @@ v "\\\\server\\share\\")
(v "\\\\server\\share\\")
(Windows)equal (rem_empty_seg @@ v "C:\\") (v "C:\\")
(Windows)equal (rem_empty_seg @@ v "C:a\\") (v "C:a")
(Windows)
Fpath.normalize
equal (normalize @@ v ".") (v "./")
equal (normalize @@ v "..") (v "../")
equal (normalize @@ v "../") (v "../")
equal (normalize @@ v "../../") (v "../../")
equal (normalize @@ v "/") (v "/")
equal (normalize @@ v "/a/b/") (v "/a/b/")
equal (normalize @@ v "/a/b") (v "/a/b")
equal (normalize @@ v "a/") (v "a/")
equal (normalize @@ v "a") (v "a")
equal (normalize @@ v "a/.") (v "a/")
equal (normalize @@ v "a/./") (v "a/")
equal (normalize @@ v "a/..") (v "./")
equal (normalize @@ v "a/../") (v "./")
equal (normalize @@ v "a/..b") (v "a/..b")
equal (normalize @@ v "./a") (v "a")
equal (normalize @@ v "../a") (v "../a")
equal (normalize @@ v "../../a") (v "../../a")
equal (normalize @@ v "./a/..") (v "./")
equal (normalize @@ v "/a/b/./..") (v "/a/")
equal (normalize @@ v "/../..") (v "/")
equal (normalize @@ v "/a/../..") (v "/")
equal (normalize @@ v "./../..") (v "../../")
equal (normalize @@ v "../../a/") (v "../../a/")
equal (normalize @@ v "/a/b/c/./../../g") (v "/a/g")
equal (normalize @@ v "/a/b/c/./../../g/") (v "/a/g/")
equal (normalize @@ v "\\\\?\\UNC\\server\\share\\..")
(v "\\\\?\\UNC\\server\\share\\")
(Windows)equal (normalize @@ v "\\\\server\\share\\")
(v "\\\\server\\share\\")
(Windows)equal (normalize @@ v "C:\\") (v "C:\\")
(Windows)equal (normalize @@ v "C:a\\") (v "C:a\\")
(Windows)
Fpath.is_prefix
is_prefix (v "/a/b") (v "/a/b") = true
is_prefix (v "/a/b") (v "/a/bc") = false
is_prefix (v "/a/b") (v "/a/b/") = true
is_prefix (v "a/b/") (v "a/b") = false
is_prefix (v "a/b/") (v "a/b/") = true
is_prefix (v "a/b/") (v "a/b/c") = true
is_prefix (v ".") (v "./") = true
is_prefix (v "..") (v ".") = false
is_prefix (v "C:a") (v "a") = false
(Windows)
Fpath.find_prefix
find_prefix (v "a/b/c") (v "a/b/d")
is Some (v "a/b/")
find_prefix (v "a/b/c") (v "a/b/cd")
is Some (v "a/b/")
find_prefix (v "a/b") (v "a/b")
is Some (v "a/b")
find_prefix (v "a/b") (v "a/b/")
is Some (v "a/b")
find_prefix (v "a/b") (v "e/f")
is None
find_prefix (v "/a/b") (v "/e/f")
is Some (v "/")
find_prefix (v "/a/b") (v "e/f")
is None
find_prefix (v "C:\\a") (v "\\a")
is None
(Windows)
Fpath.rem_prefix
rem_prefix (v "a/b/") (v "a/b")
is None
rem_prefix (v "a/b/") (v "a/b/")
is None
rem_prefix (v "a/b") (v "a/b")
is None
rem_prefix (v "a/b") (v "a/b/")
is Some "./"
rem_prefix (v "a/b") (v "a/b/c")
is Some (v "c")
rem_prefix (v "a/b/") (v "a/b/c")
is Some (v "c")
rem_prefix (v "a/b") (v "a/b/c/")
is Some (v "c/")
rem_prefix (v "a/b/") (v "a/b/c/")
is Some (v "c/")
rem_prefix (v "C:\\a") (v "C:\\a\\b")
is Some (v "b")
(Windows)
Fpath.relativize
relativize ~root:(v "/a/b") (v "c")
is None
relativize ~root:(v "/a/b") (v "/c")
is Some (v "../../c")
relativize ~root:(v "/a/b") (v "/c/")
is Some (v "../../c/")
relativize ~root:(v "/a/b") (v "/c")
is Some (v "../../c")
relativize ~root:(v "/a/b") (v "/c/")
is Some (v "../../c/")
relativize ~root:(v "/a/b") (v "/a/b/c")
is Some (v "c")
relativize ~root:(v "/a/b") (v "/a/b/c/")
is Some (v "c/")
relativize ~root:(v "/a/b") (v "/a/b")
is None
relativize ~root:(v "/a/b") (v "/a/b/")
is Some (v ".")
relativize ~root:(v "a/b") (v "/c")
is None
.relativize ~root:(v "a/b") (v "c")
is Some (v "../../c")
relativize ~root:(v "a/b") (v "c/")
is Some (v "../../c/")
relativize ~root:(v "a/b") (v "a/b/c")
is Some (v "c")
relativize ~root:(v "a/b") (v "a/b")
is Some (v ".")
relativize ~root:(v "a/b") (v "a/b/")
is Some (v ".")
relativize ~root:(v "../") (v "./")
is None
relativize ~root:(v "../a") (v "b")
is None
relativize ~root:(v "../a") (v "../b/c")
is Some (v "../b/c")
relativize ~root:(v "../../a") (v "../b")
is None
relativize ~root:(v "../a") (v "../../b")
is (Some "../../b")
Fpath.is_rooted
is_rooted ~root:(v "a/b") (v "a/b") = false
is_rooted ~root:(v "a/b") (v "a/b/") = true
is_rooted ~root:(v "a/b/") (v "a/b") = false
is_rooted ~root:(v "a/b/") (v "a/b/") = true
is_rooted ~root:(v "./") (v "a") = true
is_rooted ~root:(v "./") (v "a/") = true
is_rooted ~root:(v "./") (v "a/../") = true
is_rooted ~root:(v "./") (v "..") = false
is_rooted ~root:(v "../") (v "./") = false
is_rooted ~root:(v "../") (v "a") = false
is_rooted ~root:(v "../") (v "../") = true
is_rooted ~root:(v "../") (v "../a") = true
is_rooted ~root:(v "../a") (v "./") = false
is_rooted ~root:(v "/a") (v "/a/..") = true
is_rooted ~root:(v "/a") (v "/a/../") = true
is_rooted ~root:(v "/a") (v "/..") = true
Fpath.is_root
is_root (v "/") = true
is_root (v "/a") = false
is_root (v "/a/..") = false
is_root (v "//") = true
(POSIX)is_root (v "\\\\.\\dev\\") = true
(Windows)is_root (v "\\\\.\\dev\\a") = false
(Windows)is_root (v "\\\\server\\share\\") = true
(Windows)is_root (v "\\\\server\\share\\a") = false
(Windows)is_root (v "C:\\") = true
(Windows)is_root (v "C:a") = false
(Windows)is_root (v "C:\\a") = false
(Windows)
Fpath.get_ext
get_ext (v "/") = ""
get_ext (v "a/b") = ""
get_ext (v "a/b.mli/..") = ""
get_ext (v "a/b.mli/...") = ""
get_ext (v "a/b.") = "."
get_ext (v "a/b.mli") = ".mli"
get_ext ~multi:true (v "a/b.mli") = ".mli"
get_ext (v "a/b.mli/") = ".mli"
get_ext (v "a/.ocamlinit") = ""
get_ext (v "a/.emacs.d") = ".d"
get_ext (v "a/.emacs.d/") = ".d"
get_ext ~multi:true (v "a/.emacs.d") = ".d"
get_ext (v "a.tar.gz") = ".gz"
get_ext ~multi:true (v "a.tar.gz") = ".tar.gz"
Fpath.has_ext
has_ext "mli" (v "a/b.mli") = true
has_ext ".mli" (v "a/b.mli") = true
has_ext ".mli" (v "a/b.mli/") = true
has_ext ".mli" (v "a/bmli") = false
has_ext "mli" (v "a/bmli") = false
has_ext ".tar.gz" (v "a/f.tar.gz") = true
has_ext "tar.gz" (v "a/f.tar.gz") = true
has_ext ".gz" (v "a/f.tar.gz") = true
has_ext ".tar" (v "a/f.tar.gz") = false
has_ext ".cache" (v "a/.cache") = false
has_ext "" (v "a/b") = false
has_ext "" (v "a/b.") = true
has_ext "." (v "a/b.") = true
Fpath.exists_ext
exists_ext (v "a/f") = false
exists_ext (v "a/f.") = true
exists_ext (v "a/f.gz") = true
exists_ext ~multi:true (v "a/f.gz") = false
exists_ext (v "a/f.tar.gz") = true
exists_ext ~multi:true (v "a/f.tar.gz") = true
exists_ext (v "a/f.tar.gz/") = true
exists_ext (v ".emacs.d") = true
exists_ext (v ".emacs.d/") = true
exists_ext (v ".ocamlinit") = false
Fpath.add_ext
equal (add_ext "mli" (v "a/b")) (v "a/b.mli")
equal (add_ext ".mli" (v "a/b")) (v "a/b.mli")
equal (add_ext ".mli" (v "a/b/")) (v "a/b.mli/")
equal (add_ext ".mli" (v "/")) (v "/")
equal (add_ext ".mli" (v "a/b/..")) (v "a/b/..")
equal (add_ext "." (v "a/b")) (v "a/b.")
equal (add_ext "" (v "a/b")) (v "a/b")
equal (add_ext "tar.gz" (v "a/f")) (v "a/f.tar.gz")
equal (add_ext ".tar.gz" (v "a/f")) (v "a/f.tar.gz")
equal (add_ext "gz" (v "a/f.tar") ) (v "a/f.tar.gz")
equal (add_ext ".gz" (v "a/f.tar") ) (v "a/f.tar.gz")
Fpath.rem_ext
equal (rem_ext @@ v "/") (v "/")
equal (rem_ext @@ v "/a/b") (v "/a/b")
equal (rem_ext @@ v "/a/b.mli") (v "/a/b")
equal (rem_ext @@ v "/a/b.mli/") (v "/a/b/")
equal (rem_ext @@ v "/a/b.mli/..") (v "/a/b.mli/..")
equal (rem_ext @@ v "/a/b.mli/.") (v "/a/b.mli/.")
equal (rem_ext @@ v "a/.ocamlinit") (v "a/.ocamlinit")
equal (rem_ext @@ v "a/.emacs.d") (v "a/.emacs")
equal (rem_ext @@ v "a/.emacs.d/") (v "a/.emacs/")
equal (rem_ext @@ v "f.tar.gz") (v "f.tar")
equal (rem_ext ~multi:true @@ v "f.tar.gz") (v "f")
equal (rem_ext ~multi:true @@ v "f.tar.gz/") (v "f/")