github.com/AndrewDeryabin/doublestar/v4@v4.0.0-20230123132908-d9476b7d41be/README.md (about) 1 # doublestar 2 3 Path pattern matching and globbing supporting `doublestar` (`**`) patterns. 4 5 [![PkgGoDev](https://pkg.go.dev/badge/github.com/bmatcuk/doublestar)](https://pkg.go.dev/github.com/bmatcuk/doublestar/v4) 6 [![Release](https://img.shields.io/github/release/bmatcuk/doublestar.svg?branch=master)](https://github.com/bmatcuk/doublestar/releases) 7 [![Build Status](https://github.com/bmatcuk/doublestar/actions/workflows/test.yml/badge.svg)](https://github.com/bmatcuk/doublestar/actions) 8 [![codecov.io](https://img.shields.io/codecov/c/github/bmatcuk/doublestar.svg?branch=master)](https://codecov.io/github/bmatcuk/doublestar?branch=master) 9 [![Sponsor](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86)](https://github.com/sponsors/bmatcuk) 10 11 ## About 12 13 #### [Upgrading?](UPGRADING.md) 14 15 **doublestar** is a [golang] implementation of path pattern matching and 16 globbing with support for "doublestar" (aka globstar: `**`) patterns. 17 18 doublestar patterns match files and directories recursively. For example, if 19 you had the following directory structure: 20 21 ```bash 22 grandparent 23 `-- parent 24 |-- child1 25 `-- child2 26 ``` 27 28 You could find the children with patterns such as: `**/child*`, 29 `grandparent/**/child?`, `**/parent/*`, or even just `**` by itself (which will 30 return all files and directories recursively). 31 32 Bash's globstar is doublestar's inspiration and, as such, works similarly. 33 Note that the doublestar must appear as a path component by itself. A pattern 34 such as `/path**` is invalid and will be treated the same as `/path*`, but 35 `/path*/**` should achieve the desired result. Additionally, `/path/**` will 36 match all directories and files under the path directory, but `/path/**/` will 37 only match directories. 38 39 v4 is a complete rewrite with a focus on performance. Additionally, 40 [doublestar] has been updated to use the new [io/fs] package for filesystem 41 access. As a result, it is only supported by [golang] v1.16+. 42 43 ## Installation 44 45 **doublestar** can be installed via `go get`: 46 47 ```bash 48 go get github.com/bmatcuk/doublestar/v4 49 ``` 50 51 To use it in your code, you must import it: 52 53 ```go 54 import "github.com/bmatcuk/doublestar/v4" 55 ``` 56 57 ## Usage 58 59 ### ErrBadPattern 60 61 ```go 62 doublestar.ErrBadPattern 63 ``` 64 65 Returned by various functions to report that the pattern is malformed. At the 66 moment, this value is equal to `path.ErrBadPattern`, but, for portability, this 67 equivalence should probably not be relied upon. 68 69 ### Match 70 71 ```go 72 func Match(pattern, name string) (bool, error) 73 ``` 74 75 Match returns true if `name` matches the file name `pattern` ([see 76 "patterns"]). `name` and `pattern` are split on forward slash (`/`) characters 77 and may be relative or absolute. 78 79 Match requires pattern to match all of name, not just a substring. The only 80 possible returned error is `ErrBadPattern`, when pattern is malformed. 81 82 Note: this is meant as a drop-in replacement for `path.Match()` which always 83 uses `'/'` as the path separator. If you want to support systems which use a 84 different path separator (such as Windows), what you want is `PathMatch()`. 85 Alternatively, you can run `filepath.ToSlash()` on both pattern and name and 86 then use this function. 87 88 Note: users should _not_ count on the returned error, 89 `doublestar.ErrBadPattern`, being equal to `path.ErrBadPattern`. 90 91 92 ### PathMatch 93 94 ```go 95 func PathMatch(pattern, name string) (bool, error) 96 ``` 97 98 PathMatch returns true if `name` matches the file name `pattern` ([see 99 "patterns"]). The difference between Match and PathMatch is that PathMatch will 100 automatically use your system's path separator to split `name` and `pattern`. 101 On systems where the path separator is `'\'`, escaping will be disabled. 102 103 Note: this is meant as a drop-in replacement for `filepath.Match()`. It assumes 104 that both `pattern` and `name` are using the system's path separator. If you 105 can't be sure of that, use `filepath.ToSlash()` on both `pattern` and `name`, 106 and then use the `Match()` function instead. 107 108 ### GlobOption 109 110 Options that may be passed to `Glob`, `GlobWalk`, or `FilepathGlob`. Any number 111 of options may be passed to these functions, and in any order, as the last 112 argument(s). 113 114 ```go 115 WithFailOnIOErrors() 116 ``` 117 118 If passed, doublestar will abort and return IO errors when encountered. Note 119 that if the glob pattern references a path that does not exist (such as 120 `nonexistent/path/*`), this is _not_ considered an IO error: it is considered a 121 pattern with no matches. 122 123 ```go 124 WithFailOnPatternNotExist() 125 ``` 126 127 If passed, doublestar will abort and return `doublestar.ErrPatternNotExist` if 128 the pattern references a path that does not exist before any meta characters 129 such as `nonexistent/path/*`. Note that alts (ie, `{...}`) are expanded before 130 this check. In other words, a pattern such as `{a,b}/*` may fail if either `a` 131 or `b` do not exist but `*/{a,b}` will never fail because the star may match 132 nothing. 133 134 ```go 135 WithFilesOnly() 136 ``` 137 138 If passed, doublestar will only return "files" from `Glob`, `GlobWalk`, or 139 `FilepathGlob`. In this context, "files" are anything that is not a directory 140 or a symlink to a directory. 141 142 Note: if combined with the WithNoFollow option, symlinks to directories _will_ 143 be included in the result since no attempt is made to follow the symlink. 144 145 ```go 146 WithNoFollow() 147 ``` 148 149 If passed, doublestar will not follow symlinks while traversing the filesystem. 150 However, due to io/fs's _very_ poor support for querying the filesystem about 151 symlinks, there's a caveat here: if part of the pattern before any meta 152 characters contains a reference to a symlink, it will be followed. For example, 153 a pattern such as `path/to/symlink/*` will be followed assuming it is a valid 154 symlink to a directory. However, from this same example, a pattern such as 155 `path/to/**` will not traverse the `symlink`, nor would `path/*/symlink/*` 156 157 Note: if combined with the WithFilesOnly option, symlinks to directories _will_ 158 be included in the result since no attempt is made to follow the symlink. 159 160 ### Glob 161 162 ```go 163 func Glob(fsys fs.FS, pattern string, opts ...GlobOption) ([]string, error) 164 ``` 165 166 Glob returns the names of all files matching pattern or nil if there is no 167 matching file. The syntax of patterns is the same as in `Match()`. The pattern 168 may describe hierarchical names such as `usr/*/bin/ed`. 169 170 Glob ignores file system errors such as I/O errors reading directories by 171 default. The only possible returned error is `ErrBadPattern`, reporting that 172 the pattern is malformed. 173 174 To enable aborting on I/O errors, the `WithFailOnIOErrors` option can be 175 passed. 176 177 Note: this is meant as a drop-in replacement for `io/fs.Glob()`. Like 178 `io/fs.Glob()`, this function assumes that your pattern uses `/` as the path 179 separator even if that's not correct for your OS (like Windows). If you aren't 180 sure if that's the case, you can use `filepath.ToSlash()` on your pattern 181 before calling `Glob()`. 182 183 Like `io/fs.Glob()`, patterns containing `/./`, `/../`, or starting with `/` 184 will return no results and no errors. This seems to be a [conscious 185 decision](https://github.com/golang/go/issues/44092#issuecomment-774132549), 186 even if counter-intuitive. You can use [SplitPattern] to divide a pattern into 187 a base path (to initialize an `FS` object) and pattern. 188 189 Note: users should _not_ count on the returned error, 190 `doublestar.ErrBadPattern`, being equal to `path.ErrBadPattern`. 191 192 ### GlobWalk 193 194 ```go 195 type GlobWalkFunc func(path string, d fs.DirEntry) error 196 197 func GlobWalk(fsys fs.FS, pattern string, fn GlobWalkFunc, opts ...GlobOption) error 198 ``` 199 200 GlobWalk calls the callback function `fn` for every file matching pattern. The 201 syntax of pattern is the same as in Match() and the behavior is the same as 202 Glob(), with regard to limitations (such as patterns containing `/./`, `/../`, 203 or starting with `/`). The pattern may describe hierarchical names such as 204 usr/*/bin/ed. 205 206 GlobWalk may have a small performance benefit over Glob if you do not need a 207 slice of matches because it can avoid allocating memory for the matches. 208 Additionally, GlobWalk gives you access to the `fs.DirEntry` objects for each 209 match, and lets you quit early by returning a non-nil error from your callback 210 function. Like `io/fs.WalkDir`, if your callback returns `SkipDir`, GlobWalk 211 will skip the current directory. This means that if the current path _is_ a 212 directory, GlobWalk will not recurse into it. If the current path is not a 213 directory, the rest of the parent directory will be skipped. 214 215 GlobWalk ignores file system errors such as I/O errors reading directories by 216 default. GlobWalk may return `ErrBadPattern`, reporting that the pattern is 217 malformed. 218 219 To enable aborting on I/O errors, the `WithFailOnIOErrors` option can be 220 passed. 221 222 Additionally, if the callback function `fn` returns an error, GlobWalk will 223 exit immediately and return that error. 224 225 Like Glob(), this function assumes that your pattern uses `/` as the path 226 separator even if that's not correct for your OS (like Windows). If you aren't 227 sure if that's the case, you can use filepath.ToSlash() on your pattern before 228 calling GlobWalk(). 229 230 Note: users should _not_ count on the returned error, 231 `doublestar.ErrBadPattern`, being equal to `path.ErrBadPattern`. 232 233 ### FilepathGlob 234 235 ```go 236 func FilepathGlob(pattern string, opts ...GlobOption) (matches []string, err error) 237 ``` 238 239 FilepathGlob returns the names of all files matching pattern or nil if there is 240 no matching file. The syntax of pattern is the same as in Match(). The pattern 241 may describe hierarchical names such as usr/*/bin/ed. 242 243 FilepathGlob ignores file system errors such as I/O errors reading directories 244 by default. The only possible returned error is `ErrBadPattern`, reporting that 245 the pattern is malformed. 246 247 To enable aborting on I/O errors, the `WithFailOnIOErrors` option can be 248 passed. 249 250 Note: FilepathGlob is a convenience function that is meant as a drop-in 251 replacement for `path/filepath.Glob()` for users who don't need the 252 complication of io/fs. Basically, it: 253 254 * Runs `filepath.Clean()` and `ToSlash()` on the pattern 255 * Runs `SplitPattern()` to get a base path and a pattern to Glob 256 * Creates an FS object from the base path and `Glob()s` on the pattern 257 * Joins the base path with all of the matches from `Glob()` 258 259 Returned paths will use the system's path separator, just like 260 `filepath.Glob()`. 261 262 Note: the returned error `doublestar.ErrBadPattern` is not equal to 263 `filepath.ErrBadPattern`. 264 265 ### SplitPattern 266 267 ```go 268 func SplitPattern(p string) (base, pattern string) 269 ``` 270 271 SplitPattern is a utility function. Given a pattern, SplitPattern will return 272 two strings: the first string is everything up to the last slash (`/`) that 273 appears _before_ any unescaped "meta" characters (ie, `*?[{`). The second 274 string is everything after that slash. For example, given the pattern: 275 276 ``` 277 ../../path/to/meta*/** 278 ^----------- split here 279 ``` 280 281 SplitPattern returns "../../path/to" and "meta*/**". This is useful for 282 initializing os.DirFS() to call Glob() because Glob() will silently fail if 283 your pattern includes `/./` or `/../`. For example: 284 285 ```go 286 base, pattern := SplitPattern("../../path/to/meta*/**") 287 fsys := os.DirFS(base) 288 matches, err := Glob(fsys, pattern) 289 ``` 290 291 If SplitPattern cannot find somewhere to split the pattern (for example, 292 `meta*/**`), it will return "." and the unaltered pattern (`meta*/**` in this 293 example). 294 295 Of course, it is your responsibility to decide if the returned base path is 296 "safe" in the context of your application. Perhaps you could use Match() to 297 validate against a list of approved base directories? 298 299 ### ValidatePattern 300 301 ```go 302 func ValidatePattern(s string) bool 303 ``` 304 305 Validate a pattern. Patterns are validated while they run in Match(), 306 PathMatch(), and Glob(), so, you normally wouldn't need to call this. However, 307 there are cases where this might be useful: for example, if your program allows 308 a user to enter a pattern that you'll run at a later time, you might want to 309 validate it. 310 311 ValidatePattern assumes your pattern uses '/' as the path separator. 312 313 ### ValidatePathPattern 314 315 ```go 316 func ValidatePathPattern(s string) bool 317 ``` 318 319 Like ValidatePattern, only uses your OS path separator. In other words, use 320 ValidatePattern if you would normally use Match() or Glob(). Use 321 ValidatePathPattern if you would normally use PathMatch(). Keep in mind, Glob() 322 requires '/' separators, even if your OS uses something else. 323 324 ### Patterns 325 326 **doublestar** supports the following special terms in the patterns: 327 328 Special Terms | Meaning 329 ------------- | ------- 330 `*` | matches any sequence of non-path-separators 331 `/**/` | matches zero or more directories 332 `?` | matches any single non-path-separator character 333 `[class]` | matches any single non-path-separator character against a class of characters ([see "character classes"]) 334 `{alt1,...}` | matches a sequence of characters if one of the comma-separated alternatives matches 335 336 Any character with a special meaning can be escaped with a backslash (`\`). 337 338 A doublestar (`**`) should appear surrounded by path separators such as `/**/`. 339 A mid-pattern doublestar (`**`) behaves like bash's globstar option: a pattern 340 such as `path/to/**.txt` would return the same results as `path/to/*.txt`. The 341 pattern you're looking for is `path/to/**/*.txt`. 342 343 #### Character Classes 344 345 Character classes support the following: 346 347 Class | Meaning 348 ---------- | ------- 349 `[abc]` | matches any single character within the set 350 `[a-z]` | matches any single character in the range 351 `[^class]` | matches any single character which does *not* match the class 352 `[!class]` | same as `^`: negates the class 353 354 ## Performance 355 356 ``` 357 goos: darwin 358 goarch: amd64 359 pkg: github.com/bmatcuk/doublestar/v4 360 cpu: Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz 361 BenchmarkMatch-8 285639 3868 ns/op 0 B/op 0 allocs/op 362 BenchmarkGoMatch-8 286945 3726 ns/op 0 B/op 0 allocs/op 363 BenchmarkPathMatch-8 320511 3493 ns/op 0 B/op 0 allocs/op 364 BenchmarkGoPathMatch-8 304236 3434 ns/op 0 B/op 0 allocs/op 365 BenchmarkGlob-8 466 2501123 ns/op 190225 B/op 2849 allocs/op 366 BenchmarkGlobWalk-8 476 2536293 ns/op 184017 B/op 2750 allocs/op 367 BenchmarkGoGlob-8 463 2574836 ns/op 194249 B/op 2929 allocs/op 368 ``` 369 370 These benchmarks (in `doublestar_test.go`) compare Match() to path.Match(), 371 PathMath() to filepath.Match(), and Glob() + GlobWalk() to io/fs.Glob(). They 372 only run patterns that the standard go packages can understand as well (so, no 373 `{alts}` or `**`) for a fair comparison. Of course, alts and doublestars will 374 be less performant than the other pattern meta characters. 375 376 Alts are essentially like running multiple patterns, the number of which can 377 get large if your pattern has alts nested inside alts. This affects both 378 matching (ie, Match()) and globbing (Glob()). 379 380 `**` performance in matching is actually pretty similar to a regular `*`, but 381 can cause a large number of reads when globbing as it will need to recursively 382 traverse your filesystem. 383 384 ## Sponsors 385 I started this project in 2014 in my spare time and have been maintaining it 386 ever since. In that time, it has grown into one of the most popular globbing 387 libraries in the Go ecosystem. So, if **doublestar** is a useful library in 388 your project, consider [sponsoring] my work! I'd really appreciate it! 389 390 [![reviewpad](../sponsors/reviewpad.png?raw=true)](https://reviewpad.com/) 391 392 Thanks for sponsoring me! 393 394 ## License 395 396 [MIT License](LICENSE) 397 398 [SplitPattern]: #splitpattern 399 [doublestar]: https://github.com/bmatcuk/doublestar 400 [golang]: http://golang.org/ 401 [io/fs]: https://pkg.go.dev/io/fs 402 [see "character classes"]: #character-classes 403 [see "patterns"]: #patterns 404 [sponsoring]: https://github.com/sponsors/bmatcuk