duras/syto
1
0
Fork
You've already forked syto
0
POSIX fnmatch(3) filename pattern matching https://opam.ocaml.org/packages/syto/
  • OCaml 97%
  • Dune 3%
2026年06月10日 23:20:48 +03:00
docs Initial commit 2026年06月10日 20:24:52 +03:00
lib Initial commit 2026年06月10日 21:09:02 +03:00
test Initial commit 2026年06月10日 21:09:02 +03:00
.gitignore initial commit 2026年06月10日 21:31:45 +03:00
CHANGES.md Switch source to GitHub mirror for opam release 2026年06月10日 23:20:48 +03:00
dune-project Switch source to GitHub mirror for opam release 2026年06月10日 23:20:48 +03:00
LICENSE Initial commit 2026年06月10日 21:09:02 +03:00
README.md initial commit 2026年06月10日 19:58:06 +03:00
syto.opam Switch source to GitHub mirror for opam release 2026年06月10日 23:20:48 +03:00

syto

POSIX fnmatch(3) filename pattern matching for OCaml.

Installation

opam install syto

Minimum OCaml version: 4.14.

Examples

All examples run in utop after #require "syto";;.

Literal and wildcard

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"] *)

PATHNAME — slashes are path boundaries

* 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 *)

PERIOD — dotfiles require an explicit dot

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 *)

CASEFOLD — case-insensitive matching (ASCII)

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"] *)

GLOBSTAR — recursive path matching

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"] *)

Flags

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

filter vs match_pattern

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.

POSIX deviations

  • Matching operates on UTF-8 codepoints, not locale-dependent bytes. ? matches one Unicode codepoint.
  • Collating elements [.ch.] and equivalence classes [=a=] raise Error.
  • [a-b-c] raises Error; POSIX parses it as range a-b plus literal -c.
  • CASEFOLD folds ASCII A–Z only. Cyrillic and other non-ASCII letters are compared by codepoint value.
  • GLOBSTAR is a non-POSIX extension (common in bash and gitignore).

Documentation

Extended examples and integration patterns: docs/guide.md.

API reference: dune build @doc or the opam package documentation.

License

ISC. See LICENSE.