Module B00_std.Fpath

File paths.

A file system path specifies a file or a directory in a file system hierarchy. It is made of three parts:

  1. An optional, platform-dependent, volume.
  2. An optional root directory separator dir_sep whose presence distinguishes absolute paths ("/a") from relative ones ("a")
  3. A non-empty list of dir_sep separated segments. Segments are non empty strings except for maybe the last one. The latter syntactically distinguishes directory paths ("a/b/") from file paths ("a/b").

The paths 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 (e.g. on "/" or "..").

Separators and segments

val dir_sep_char : char

dir_sep_char is the platform dependent natural directory separator. This is / on POSIX and \ on Windows.

val dir_sep : string

dir_sep is dir_sep_char as a string.

val has_dir_sep : string -> bool

has_dir_sep s is true iff s contains dir_sep_char (on Windows also if it contains '/').

val is_seg : string -> bool

is_seg s is true iff s does not contain a dir_sep_char (on Windows also that it does not contain '/') or a null byte.

val is_rel_seg : string -> bool

is_rel_seg s is true iff s is a relative segment in other words either "." or "..".

Paths

type t

The type for paths

val v : string -> t

v s is the string s as a path.

Warning. In code only use "/" as the directory separator even on Windows platforms (don't be upset, the module gives them back to you with backslashes).

raises Invalid_argument

if s is not a valid path. Use of_string to deal with untrusted input.

val add_seg : t -> string -> t

add_seg p seg if p's last segment is non-empty this is p with seg added. If p's last segment is empty, this is p with the empty segment replaced by seg.

raises Invalid_argument

if is_seg seg is false.

val append : t -> t -> t

append p q appends q to p as follows:

  • If q is absolute or has a non-empty volume then q is returned.
  • Otherwise appends q's segments to p using add_seg.
val (/) : t -> string -> t

p / seg is add_seg p seg. Left associative.

val (//) : t -> t -> t

p // p' is append p p'. Left associative.

Directory paths

val is_dir_path : t -> bool

is_dir_path p is true iff p syntactically represents a directory. This means that p is ., .. or ends with /, /. or /...

val to_dir_path : t -> t

to_dir_path p is add_seg p "". It ensures that the resulting path syntactically represents a directory and thus, if converted to a string, that it ends with a dir_sep.

val rem_empty_seg : t -> t

rem_empty_seg p is p without an existing last empty segment when p is not a root path, ensuring the result has no trailing dir_sep when converted to a string.

Basename and parent directory

val basename : ?⁠no_ext:bool -> t -> string

basename p is the last non-empty segment of p or the empty string otherwise. The latter occurs only on root paths and on paths whose last non-empty segment is a relative segment. If no_ext is true (default to false) the basename's multiple extension, if any, is removed from the result.

val parent : t -> t

parent p is a directory path that contains p. If p is a root path this is p itself. If p is in the current directory this is ./.

Strict prefixes and roots

val is_prefix : t -> t -> bool

is_prefix prefix p is true iff prefix is a strict prefix of p that respects path segments. More formally iff the following two conditions hold:

  1. not Fpath.(equal (to_dir_path prefix) (to_dir_path p))
  2. Fpath.(String.is_prefix (to_string (to_dir_path prefix) (to_string p))) is true

Warning. By definition is_prefix p p is false. Note also that the prefix relation does not entail directory containement; for example is_prefix (v "..") (v "../..") holds.

val rem_prefix : t -> t -> t option

rem_prefix prefix p is:

  • None if is_prefix prefix p is false.
  • Some q otherwise where q is p without the string prefix Fpath.to_dir_path prefix. This means that q is always relative, that it preserves p's directoryness and that Fpath.(equal (prefix // q) p) holds.

Warning. By definition rem_prefix p p is None.

val drop_prefixed : t list -> t list

drop_prefixed ps is ps without elements that have a strict prefixes in ps. The list order is preserved. Duplicates are not removed use uniquify for this.

val reroot : root:t -> dst:t -> t -> t

reroot ~root ~dst p assumes root prefixes p removes the prefix and prepends dst to the result.

raises Invalid_argument

if root is not a prefix of src. In particular note that p cannot be root.

val relative : to_dir:t -> t -> t

relative to_dir p is q such that to_dir // q represents the same path as p. Note that q is not necessarily relative: if to_dir is relative and p is absolute p is returned.

raises Invalid_argument

if path to_dir contains "..".

Predicates and comparison

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.

val is_current_dir : t -> bool

is_current_dir p is true iff p is either "." or "./".

val is_parent_dir : t -> bool

is_parent_dir p is true iff p is either ".." or "../".

val equal : t -> t -> bool

equal p0 p1 is true iff p0 and p1 are stringwise equal.

val equal_basename : t -> t -> bool

equal_basename p0 p1 is String.equal (basename p0) (basename p1).

val compare : t -> t -> int

compare p0 p1 is a total order on paths compatible with equal.

File extensions

type ext = string

The type for file extensions, '.' separator included.

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.

val has_ext : ext -> t -> bool

has_ext ext p is true iff String.equal (get_ext p) e || String.equal (get_ext ~multi:true p) e.

val mem_ext : ext list -> t -> bool

mem_ext exts p is List.exists (fun e -> has_ext e p) exts

val add_ext : ext -> t -> t

add_ext ext p is p with ext concatenated to p's basename.

val rem_ext : ?⁠multi:bool -> t -> t

rem_ext ?multi p is p with the extension of p's basename removed. If multi is true (defaults to false), the multiple file extension is removed.

val set_ext : ?⁠multi:bool -> ext -> t -> t

set_ext ?multi p is add_ext ext (rem_ext ?multi p).

val cut_ext : ?⁠multi:bool -> t -> t * ext

cut_ext ?multi p is (rem_ext ?multi p, get_ext ?multi p).

val (+) : t -> ext -> t

p + ext is add_ext p ext. Left associative.

val (-+) : t -> ext -> t

p -+ ext is set_ext p ext. Left associative.

Converting

val of_string : string -> (t, string) Stdlib.result

of_string s is the string s as a path. The following transformations are performed on the string:

  • On Windows any / (0x2F) occurence is converted to \ (0x5C)
  • Non initial empty segments are suppressed; "a//b" becomes "a/b", "//a////b//" becomes "//a/b/", etc

An error returned if s is "" or if it contains a null byte. The error string mentions s.

val to_string : t -> string

to_string p is the path p as a string. The result can be safely converted back with v.

val to_uri_path : ?⁠escape_space:bool -> t -> string

to_uri_path p is the path p as an URI path. This is p with the system specific dir_sep_char directory separator replaced by '/' and with the following characters percent encoded: '%', '?', '#', ' ' (unless escape_space is false, defaults to true), and the US-ASCII control characters.

Note. In 2019, the standard definition of URIs is in a sorry state. Assuming p is UTF-8 encoded. It is believed the above function should lead to an URI path component that can be parsed by HTML5's definition of URI parsing.

val pp_quoted : t Fmt.t

pp_quoted ppf p prints path p on ppf using Filename.quote.

val pp_unquoted : t Fmt.t

pp_unquoted p prints path p on ppf using to_string.

val pp_dump : t Fmt.t

pp_dump ppf p prints path p on ppf using String.dump.

Uniqueness

val uniquify : t list -> t list

uniquify ps is ps without duplicates, the list order is preserved.

Paths map and sets

type path = t
module Set : sig ... end

Path sets.

module Map : sig ... end

Path maps.

Sorts

val sort_by_parent : Set.t -> Set.t Map.t

sort_by_parent ps maps elements of ps by their Fpath.parent.

val sort_by_ext : ?⁠multi:bool -> Set.t -> Set.t String.Map.t

sort_by_ext ~multi ps maps elements of ps by their extension as determined by Fpath.get_ext ~multi.

Search paths

val search_path_sep : string

search_path_sep is the default platform specific separator for search paths, this is ";" if Sys.win32 is true and ":" otherwise.

val list_of_search_path : ?⁠sep:string -> string -> (t list, string) Stdlib.result

list_of_search_path ~sep s parses sep separated file paths from s. sep is not allowed to appear in the file paths, it defaults to search_path_sep. The order in the list matches the order from left to right in s.