POSIX fnmatch(3) filename pattern matching for OCaml.
opam install syto
Minimum OCaml version: 4.14.
All examples run in utop after #require "syto";;.
Syto.match_pattern ~pattern:"*.ml" ~name:"foo.ml";;
(* - : bool = true *)
Syto.filter ~pattern:"*.ml" ["foo.ml"; "bar.txt"; "baz.ml"];;
(* - : string list = ["foo.ml"; "baz.ml"] *)* and ? do not cross / when PATHNAME is set.
(* Without PATHNAME: * matches anything including / *)
Syto.match_pattern ~pattern:"*.ml" ~name:"src/foo.ml";;
(* - : bool = true *)
(* With PATHNAME: * stops at / *)
Syto.match_pattern ~flags:[`PATHNAME] ~pattern:"*.ml" ~name:"src/foo.ml";;
(* - : bool = false *)
Syto.match_pattern ~flags:[`PATHNAME] ~pattern:"src/*.ml" ~name:"src/foo.ml";;
(* - : bool = true *)With PERIOD, a name component beginning with . is matched only by a
pattern with a literal . at that position. Wildcards do not match it.
Syto.match_pattern ~flags:[`PERIOD] ~pattern:"*" ~name:".gitignore";;
(* - : bool = false *)
Syto.match_pattern ~flags:[`PERIOD] ~pattern:".*" ~name:".gitignore";;
(* - : bool = true *)
(* PERIOD applies after each / when PATHNAME is also set *)
Syto.match_pattern ~flags:[`PATHNAME; `PERIOD]
~pattern:"src/*" ~name:"src/.hidden";;
(* - : bool = false *)Syto.match_pattern ~flags:[`CASEFOLD] ~pattern:"*.ML" ~name:"foo.ml";;
(* - : bool = true *)
Syto.filter ~flags:[`CASEFOLD] ~pattern:"readme*"
["README.md"; "readme.txt"; "notes.md"];;
(* - : string list = ["README.md"; "readme.txt"] *)With PATHNAME and GLOBSTAR, ** matches zero or more path components.
let flags = [`PATHNAME; `GLOBSTAR];;
Syto.match_pattern ~flags ~pattern:"src/**/*.ml" ~name:"src/lib/foo.ml";;
(* - : bool = true *)
Syto.match_pattern ~flags ~pattern:"src/**/*.ml" ~name:"src/foo.ml";;
(* - : bool = true — ** matches zero components *)
Syto.match_pattern ~flags ~pattern:"a/**" ~name:"a";;
(* - : bool = false — trailing ** requires at least one boundary *)
Syto.filter ~flags ~pattern:"**/*.ml"
["src/a.ml"; "src/lib/b.ml"; "other.txt"];;
(* - : string list = ["src/a.ml"; "src/lib/b.ml"] *)| Flag | POSIX? | Effect |
|---|---|---|
`PATHNAME |
yes | * and ? do not match /; bracket expressions do not match / |
`NOESCAPE |
yes | \ is a literal character, not an escape |
`PERIOD |
yes | a leading . requires an explicit . in the pattern |
`CASEFOLD |
no (GNU) | ASCII A–Z folded to a–z before comparison |
`GLOBSTAR |
no (bash) | ** as a complete path component matches zero or more components |
Flags may be combined freely. GLOBSTAR without PATHNAME makes **
behave identically to *.
Syto.filter ~pattern names and
List.filter (fun n -> Syto.match_pattern ~pattern ~name:n) names
produce the same result. Use filter when applying one pattern to many
names; it parses the pattern once. Use match_pattern for one-off checks
or when testing multiple patterns against one name.
- Matching operates on UTF-8 codepoints, not locale-dependent bytes.
?matches one Unicode codepoint. - Collating elements
[.ch.]and equivalence classes[=a=]raiseError. [a-b-c]raisesError; POSIX parses it as rangea-bplus literal-c.CASEFOLDfolds ASCII A–Z only. Cyrillic and other non-ASCII letters are compared by codepoint value.GLOBSTARis a non-POSIX extension (common in bash and gitignore).
Extended examples and integration patterns: docs/guide.md.
API reference: dune build @doc or the opam package documentation.
ISC. See LICENSE.