package b0

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Module B0_std.FpathSource

File paths.

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

  1. An optional, platform-dependent, volume (e.g. "C:").
  2. An optional root directory separator whose presence distinguishes absolute paths from relative ones (e.g. "/a" versus "a").
  3. A non-empty list of segments delimited by directory separators. Segments are non empty strings except for maybe the last one. The latter syntactically distinguishes directory paths from file paths (e.g. "a/b/" versus "a/b"). But a directory can also be specified by a file path and a syntactic directory path may not be a directory (e.g. a symlink).

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 "..").

Directory separators

Sourceval natural_dir_sep_char : char

natural_dir_sep_char is the natural directory separator for the platform. This is '\\' if Sys.win32 and '/' otherwise.

Warning. Do not test for equality against this character to assert directory separators. Use is_dir_sep_char, some platforms support more than one directory separator.

Sourceval natural_dir_sep : string

natural_dir_sep is natural_dir_sep_char as a string.

Warning. Do not test for equality against this string to assert directory separators. Use is_dir_sep, some platforms support more than one directory separator.

Sourceval is_dir_sep_char : char -> bool

is_dir_sep_char c is true iff c is a directory separator on the platform. This means c is '/' or it is '\\' and Sys.win32 is true.

Sourceval is_dir_sep : string -> bool

is_dir_sep s is true if s is a singelton string and is_dir_sep_char s.[0] is true.

File paths

Sourcetype t

The type for file paths.

Sourceval v : string -> t

v s is the string s as a file path. Raises Invalid_argument if s is not a valid path. Use of_string to deal with untrusted input.

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

Sourceval fmt : ('a, Format.formatter, unit, t) format4 -> 'a

fmt … is Fmt.kstr v ….

Sourceval 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_segment.
Sourceval (//) : t -> t -> t

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

Famous file paths

Sourceval null : t

null represents a file on the OS that discards all writes and returns end of file on reads. This is NUL if Sys.win32 is true and /dev/null otherwise. See also is_null.

Sourceval dash : t

dash is "-". This value is used in command line interfaces to denote standard input or output. See also is_dash.

Segments

Sourceval is_segment : string -> bool

is_segment s is true iff s does not contain a null byte or a directory separator as asserted by is_dir_sep_char.

Sourceval is_segment_relative : string -> bool

is_segment_relative s is true iff s is either "." or "..".

Sourceval add_segment : t -> string -> (t, string) result

add_segment p seg is:

  • p with the last segment replaced by seg, if the last segment is empty.
  • p with segment seg added, otherwise

This errors if is_segment seg is false. FIXME error format.

Sourceval (/) : t -> string -> t

p / seg is add_segment p seg |> Result.get_ok'. Left associative. Warning. Use add_segment to deal with untrusted seg values.

Syntactic directory paths

Sourceval is_syntactic_dir : t -> bool

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

Note. This a syntactic check, the file system may attribute different properties to these paths.

Sourceval ensure_trailing_dir_sep : t -> t

ensure_trailing_dir_sep p is add_segment p "". This ensures that p has a final empty segment and thus a trailing directory separator when converted to a string.

Sourceval strip_trailing_dir_sep : t -> t

strip_trailing_dir_sep p ensures p has no final empty segment unless p is a root path. When p is not a root path this ensure that p has no trailing directory separator when converted to a string.

Basename and parent directory

Note. The following functions use syntactic semantic properties of paths. Given a path, these properties can be different from the ones your file system attributes to it.

Sourceval basename : ?strip_exts: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 strip_exts is true (default to false) the basename's multiple extension, if any, is removed from the segment.

Sourceval basepath : ?strip_exts:bool -> t -> t

basepath is like basename but returns a file path with the result or "." if the result is empty which can be detected by is_current_dir.

Sourceval 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

Sourceval 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.

Sourceval strip_prefix : t -> t -> t option

strip_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 syntactic directoryness and that Fpath.(equal (prefix // q) p) holds.

Warning. By definition strip_prefix p p is None.

Sourceval 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 distinct for this.

Sourceval reroot : src_root:t -> dst_root:t -> t -> t

reroot ~src_root ~dst_root p assumes src_root prefixes p removes the prefix and prepends dst_root to the result.

Raises Invalid_argument if dst_root is not a prefix of src. In particular note that p cannot be src_root.

Sourceval 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.

Warning. This function is mostly broken at the moment.

Raises Invalid_argument if path to_dir contains "..".

Predicates and comparison

Sourceval is_relative : t -> bool

is_relative p is true iff p is a relative path, i.e. the root directory separator is missing in p.

Sourceval is_absolute : t -> bool

is_absolute p is true iff p is an absolute path, i.e. the root directory separator is present in p.

Sourceval 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.

Sourceval is_null : t -> bool

is_null p is equal p null.

Sourceval is_dash : t -> bool

is_dash p is equal p dash.

Sourceval is_current_dir : t -> bool

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

Sourceval is_parent_dir : t -> bool

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

Sourceval equal : t -> t -> bool

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

Sourceval equal_basename : t -> t -> bool

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

Sourceval compare : t -> t -> int

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

File extensions

The file extension (resp. multiple file extensions) 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 a single one.

TODO In the fpath package we correct e.g. has_ext if the given ext has no ext. I think we should either check and raise Invalid_argument or correct.

Sourcetype ext = string

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

Sourceval exists_ext : t -> bool

exists_ext p is true iff p has a file or multiple file extension.

Sourceval exists_multi_ext : t -> bool

exists_multi_ext p is true iff p has a multiple file extension.

Sourceval get_ext : multi:bool -> t -> ext

get_ext ~multi p is the file extension or multiple file extension if multi is true of the basename of p.

The empty string is returned if there is no extension. By definition this operates on the directory name of directory paths, not on the final empty segment.

Sourceval has_ext : ext -> t -> bool

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

Sourceval mem_ext : ext list -> t -> bool

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

Sourceval add_ext : string -> t -> t

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

Note. ext is not required to start with a . it can be used for arbitrary basename extension.

Sourceval strip_ext : multi:bool -> t -> t

strip_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.

Sourceval set_ext : multi:bool -> string -> t -> t

set_ext ~multi ext p is add_ext ext (strip_ext ~multi p).

Sourceval cut_ext : multi:bool -> t -> t * ext

cut_ext ~multi p is (strip_ext ~multi p, get_ext ~multi p).

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

p + ext is add_ext p ext. Left associative.

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

p -+ ext is set_ext ~multi:false p ext. Left associative.

Converting

Sourceval of_string : string -> (t, string) 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.

Sourceval to_string : t -> string

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

Sourceval to_url_path : ?escape_space:bool -> t -> string

to_url_path ~escape_space p is the path p as an URL path. This is p with the directory separator replaced by '/' and with the following characters percent encoded: '%', '?', '#', ' ' (if escape_space is true, default), and the US-ASCII control characters.

If Sys.win32 is true and p has a drive a '/' is prepended to the result.

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

Sourceval to_segments : t -> string list

to_segments p is p's non-empty list of segments. Absolute paths have an empty string added, this allows to recover the path's string with String.concat dir_sep, note however that you may have lost the volume along the way.

Formatting

Sourceval pp : t Fmt.t

pp ppf p prints path p on ppf. The path is quoted with Filename.quote if needed. For now this means if it contains spaces (U+0020).

Sourceval pp_quoted : t Fmt.t

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

Sourceval pp_unquoted : t Fmt.t

pp_unquoted ppf p prints path p on ppf using to_string.

Sourceval pp_dump : t Fmt.t

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

Sourceval error : t -> ('b, Format.formatter, unit, ('a, string) result) format4 -> 'b

error p fmt … is Fmt.error ("%a:" ^^ fmt) pp_unquoted p … .

Sourceval prefix_msg : t -> string -> string

prefix_msg p msg is Fmt.str "%a: %s" pp_unquoted msg.

Uniqueness

Sourceval distinct : t list -> t list

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

Paths map and sets

Sourcetype path = t
Sourcemodule Set : sig ... end

Path sets.

Sourcemodule Map : sig ... end

Path maps.

Sorts

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

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

Sourceval 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

A search path is a list of paths separated by a designated separator in which elements are looked up in left to right priority order. A well known search path is PATH in which executable binaries are looked up.

Sourceval search_path_sep : string

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

Sourceval list_of_search_path : ?sep:string -> string -> (t list, string) result

list_of_search_path ~sep s splits s on sep (defaults to search_path_sep) and parses the result with of_string, ignoring empty strings.

This means that sep is not allowed to appear in the file paths, consecutive sep are ignored and the order in the resulting list matches the left-to-right order of paths in s.

If one of_string errors on a path p with e the function errors with the message:

Fmt.str "Illegal path %a in search path: %s" pp p e