1 | # micromatch [![NPM version](https://badge.fury.io/js/micromatch.svg)](http://badge.fury.io/js/micromatch) [![Build Status](https://travis-ci.org/jonschlinkert/micromatch.svg)](https://travis-ci.org/jonschlinkert/micromatch)
|
2 |
|
3 | > Glob matching for javascript/node.js. A drop-in replacement and faster alternative to minimatch and multimatch. Just use `micromatch.isMatch()` instead of `minimatch()`, or use `micromatch()` instead of `multimatch()`.
|
4 |
|
5 | ## Features
|
6 |
|
7 | Micromatch is [10-55x faster](#benchmarks) than [minimatch], resulting from a combination of caching, tokenization, parsing, runtime compilation and regex optimization strategies.
|
8 |
|
9 | - [Drop-in replacement][switch] for [minimatch] and [multimatch]
|
10 | - Built-in support for multiple glob patterns, like `['foo/*.js', '!bar.js']`
|
11 | - Better support for the Bash 4.3 specification, and less buggy
|
12 | - Extensive [unit tests](./test) (approx. 1,300 tests). Minimatch fails many of the tests.
|
13 |
|
14 | **Supports**
|
15 |
|
16 | Mainstream glob features:
|
17 |
|
18 | + [Brace Expansion][braces] (`foo/bar-{1..5}.md`, `one/{two,three}/four.md`)
|
19 | + Typical glob patterns, like `**/*`, `a/b/*.js`, or `['foo/*.js', '!bar.js']`
|
20 |
|
21 | Extended globbing features:
|
22 |
|
23 | + Logical `OR` (`foo/bar/(abc|xyz).js`)
|
24 | + Regex character classes (`foo/bar/baz-[1-5].js`)
|
25 | + POSIX bracket expressions (`**/[[:alpha:][:digit:]]/`)
|
26 | + extglobs (`**/+(x|y)`, `!(a|b)`, etc)
|
27 |
|
28 | You can combine these to create whatever matching patterns you need.
|
29 |
|
30 |
|
31 | ## Install with [npm](npmjs.org)
|
32 |
|
33 | ```bash
|
34 | npm i micromatch --save
|
35 | ```
|
36 |
|
37 |
|
38 | ## Usage
|
39 |
|
40 | ```js
|
41 | var mm = require('micromatch');
|
42 | mm(array, patterns);
|
43 | ```
|
44 |
|
45 | **Examples**
|
46 |
|
47 | ```js
|
48 | mm(['a.js', 'b.md', 'c.txt'], '*.{js,txt}');
|
49 | //=> ['a.js', 'c.txt']
|
50 | ```
|
51 |
|
52 | **Multiple patterns**
|
53 |
|
54 | Multiple patterns can also be passed:
|
55 |
|
56 | ```js
|
57 | mm(['a.md', 'b.js', 'c.txt', 'd.json'], ['*.md', '*.txt']);
|
58 | //=> ['a.md', 'c.txt']
|
59 | ```
|
60 |
|
61 | **Negation patterns:**
|
62 |
|
63 | ```js
|
64 | mm(['a.js', 'b.md', 'c.txt'], '!*.{js,txt}');
|
65 | //=> ['b.md']
|
66 |
|
67 | mm(['a.md', 'b.js', 'c.txt', 'd.json'], ['*.*', '!*.{js,txt}']);
|
68 | //=> ['a.md', 'd.json']
|
69 | ```
|
70 |
|
71 | ## Switch from minimatch
|
72 |
|
73 | > Use `micromatch.isMatch()` instead of `minimatch()`
|
74 |
|
75 | **Minimatch**
|
76 |
|
77 | The main `minimatch()` function returns true/false for a single file path and pattern:
|
78 |
|
79 | ```js
|
80 | var minimatch = require('minimatch');
|
81 | minimatch('foo.js', '*.js');
|
82 | //=> 'true'
|
83 | ```
|
84 |
|
85 | **Micromatch**
|
86 |
|
87 | Use `.isMatch()` to get the same result:
|
88 |
|
89 |
|
90 | ```js
|
91 | var mm = require('micromatch');
|
92 | mm.isMatch('foo.js', '*.js');
|
93 | //=> 'true'
|
94 | ```
|
95 |
|
96 | This implementation difference is necessary since the main `micromatch()` method supports matching on multiple globs, with behavior similar to [multimatch].
|
97 |
|
98 |
|
99 | ## Methods
|
100 |
|
101 | ```js
|
102 | var mm = require('micromatch');
|
103 | ```
|
104 |
|
105 | ### .isMatch
|
106 |
|
107 | ```js
|
108 | mm.isMatch(filepath, globPattern);
|
109 | ```
|
110 |
|
111 | Returns true if a file path matches the given glob pattern.
|
112 |
|
113 |
|
114 | **Example**
|
115 |
|
116 | ```js
|
117 | mm.isMatch('.verb.md', '*.md');
|
118 | //=> false
|
119 |
|
120 | mm.isMatch('.verb.md', '*.md', {dot: true});
|
121 | //=> true
|
122 | ```
|
123 |
|
124 | ### .contains
|
125 |
|
126 | Returns true if any part of a file path matches the given glob pattern. Think of this is "has path" versus "is path".
|
127 |
|
128 | **Example**
|
129 |
|
130 | `.isMatch()` would return false for both of the following:
|
131 |
|
132 | ```js
|
133 | mm.contains('a/b/c', 'a/b');
|
134 | //=> true
|
135 |
|
136 | mm.contains('a/b/c', 'a/*');
|
137 | //=> true
|
138 | ```
|
139 |
|
140 | ### .matcher
|
141 |
|
142 | Returns a function for matching using the supplied pattern. e.g. create your own "matcher". The advantage of this method is that the pattern can be compiled outside of a loop.
|
143 |
|
144 | **Pattern**
|
145 |
|
146 | Can be any of the following:
|
147 |
|
148 | - `glob/string`
|
149 | - `regex`
|
150 | - `function`
|
151 |
|
152 | **Example**
|
153 |
|
154 | ```js
|
155 | var isMatch = mm.matcher('*.md');
|
156 | var files = [];
|
157 |
|
158 | ['a.md', 'b.txt', 'c.md'].forEach(function(fp) {
|
159 | if (isMatch(fp)) {
|
160 | files.push(fp);
|
161 | }
|
162 | });
|
163 | ```
|
164 |
|
165 | ### .filter
|
166 |
|
167 | Returns a function that can be passed to `Array#filter()`.
|
168 |
|
169 | **Params**
|
170 |
|
171 | - `patterns` **{String|Array}**:
|
172 |
|
173 | **Examples**
|
174 |
|
175 | Single glob:
|
176 |
|
177 | ```js
|
178 | var fn = mm.filter('*.md');
|
179 | ['a.js', 'b.txt', 'c.md'].filter(fn);
|
180 | //=> ['c.md']
|
181 |
|
182 | var fn = mm.filter('[a-c]');
|
183 | ['a', 'b', 'c', 'd', 'e'].filter(fn);
|
184 | //=> ['a', 'b', 'c']
|
185 | ```
|
186 |
|
187 | Array of glob patterns:
|
188 |
|
189 | ```js
|
190 | var arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
|
191 |
|
192 | var fn = mm.filter(['{1..10}', '![7-9]', '!{3..4}']);
|
193 | arr.filter(fn);
|
194 | //=> [1, 2, 5, 6, 10]
|
195 | ```
|
196 |
|
197 | _(Internally this function generates the matching function by using the [matcher] method. You can use the [matcher] method directly to create your own filter function)_
|
198 |
|
199 |
|
200 | ### .any
|
201 |
|
202 | Returns true if a file path matches any of the given patterns.
|
203 |
|
204 | ```js
|
205 | mm.any(filepath, patterns, options);
|
206 | ```
|
207 |
|
208 | **Params**
|
209 |
|
210 | - filepath `{String}`: The file path to test.
|
211 | - patterns `{String|Array}`: One or more glob patterns
|
212 | - options: `{Object}`: options to pass to the `.matcher()` method.
|
213 |
|
214 |
|
215 | **Example**
|
216 |
|
217 | ```js
|
218 | mm.any('abc', ['!*z']);
|
219 | //=> true
|
220 | mm.any('abc', ['a*', 'z*']);
|
221 | //=> true
|
222 | mm.any('abc', 'a*');
|
223 | //=> true
|
224 | mm.any('abc', ['z*']);
|
225 | //=> false
|
226 | ```
|
227 |
|
228 |
|
229 | ### .expand
|
230 |
|
231 | Returns an object with a regex-compatible string and tokens.
|
232 |
|
233 | ```js
|
234 | mm.expand('*.js');
|
235 |
|
236 | // when `track` is enabled (for debugging), the `history` array is used
|
237 | // to record each mutation to the glob pattern as it's converted to regex
|
238 | { options: { track: false, dot: undefined, makeRe: true, negated: false },
|
239 | pattern: '(.*\\/|^)bar\\/(?:(?!(?:^|\\/)\\.).)*?',
|
240 | history: [],
|
241 | tokens:
|
242 | { path:
|
243 | { whole: '**/bar/**',
|
244 | dirname: '**/bar/',
|
245 | filename: '**',
|
246 | basename: '**',
|
247 | extname: '',
|
248 | ext: '' },
|
249 | is:
|
250 | { glob: true,
|
251 | negated: false,
|
252 | globstar: true,
|
253 | dotfile: false,
|
254 | dotdir: false },
|
255 | match: {},
|
256 | original: '**/bar/**',
|
257 | pattern: '**/bar/**',
|
258 | base: '' } }
|
259 | ```
|
260 |
|
261 | ### .makeRe
|
262 |
|
263 | Create a regular expression for matching file paths based on the given pattern:
|
264 |
|
265 | ```js
|
266 | mm.makeRe('*.js');
|
267 | //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/
|
268 | ```
|
269 |
|
270 | ## Options
|
271 |
|
272 | All options should work the same way as [minimatch].
|
273 |
|
274 | ### options.dot
|
275 |
|
276 | Match dotfiles.
|
277 |
|
278 | Type: `{Boolean}`
|
279 |
|
280 | Default: `false`
|
281 |
|
282 |
|
283 | ### options.matchBase
|
284 |
|
285 | Allow glob patterns without slashes to match a file path based on its basename.
|
286 |
|
287 | Type: `{Boolean}`
|
288 |
|
289 | Default: `false`
|
290 |
|
291 | **Example**
|
292 |
|
293 | ```js
|
294 | mm(['a/b.js', 'a/c.md'], '*.js');
|
295 | //=> []
|
296 |
|
297 | mm(['a/b.js', 'a/c.md'], '*.js', {matchBase: true});
|
298 | //=> ['a/b.js']
|
299 | ```
|
300 |
|
301 | ### options.nobraces
|
302 |
|
303 | Don't expand braces in glob patterns.
|
304 |
|
305 | Type: `{Boolean}`
|
306 |
|
307 | Default: `false`
|
308 |
|
309 |
|
310 | ### options.nocase
|
311 |
|
312 | Use a case-insensitive regex for matching files.
|
313 |
|
314 | Type: `{Boolean}`
|
315 |
|
316 | Default: `false`
|
317 |
|
318 |
|
319 | ### options.nonull
|
320 |
|
321 | If `true`, when no matches are found the actual (array-ified) glob pattern is returned instead of an empty array.
|
322 |
|
323 | Type: `{Boolean}`
|
324 |
|
325 | Default: `false`
|
326 |
|
327 |
|
328 | ### options.cache
|
329 |
|
330 | Cache the platform (e.g. `win32`) to prevent this from being looked up for every fil.
|
331 |
|
332 | Type: `{Boolean}`
|
333 |
|
334 | Default: `true`
|
335 |
|
336 |
|
337 | ## Other features
|
338 |
|
339 | Micromatch also supports the following.
|
340 |
|
341 | ### Extended globbing
|
342 |
|
343 | Extended globbing as described by the bash man page:
|
344 |
|
345 | | **pattern** | **regex equivalent** | **description** |
|
346 | | --- | --- | --- |
|
347 | | `?(pattern-list)` | `(...|...)?` | Matches zero or one occurrence of the given patterns |
|
348 | | `*(pattern-list)` | `(...|...)*` | Matches zero or more occurrences of the given patterns |
|
349 | | `+(pattern-list)` | `(...|...)+` | Matches one or more occurrences of the given patterns |
|
350 | | `@(pattern-list)` | `(...|...)` <sup>*</sup> | Matches one of the given patterns |
|
351 | | `!(pattern-list)` | N/A | Matches anything except one of the given patterns |
|
352 |
|
353 | <sup><strong>*</strong></sup> `@` isn't a RegEx character.
|
354 |
|
355 |
|
356 | ### Brace Expansion
|
357 |
|
358 | In simple cases, brace expansion appears to work the same way as the logical `OR` operator. For example, `(a|b)` will achieve the same result as `{a,b}`.
|
359 |
|
360 | Here are some powerful features unique to brace expansion (versus character classes):
|
361 |
|
362 | - range expansion: `a{1..3}b/*.js` expands to: `['a1b/*.js', 'a2b/*.js', 'a3b/*.js']`
|
363 | - nesting: `a{c,{d,e}}b/*.js` expands to: `['acb/*.js', 'adb/*.js', 'aeb/*.js']`
|
364 |
|
365 |
|
366 | Learn about [brace expansion][braces], or visit [braces][braces] to ask questions and create an issue related to brace-expansion, or to see the full range of features and options related to brace expansion.
|
367 |
|
368 |
|
369 | ### Regex character classes
|
370 |
|
371 | With the exception of brace expansion (`{a,b}`, `{1..5}`, etc), most of the special characters convert directly to regex, so you can expect them to follow the same rules and produce the same results as regex.
|
372 |
|
373 | For example, given the list: `['a.js', 'b.js', 'c.js', 'd.js', 'E.js']`:
|
374 |
|
375 | - `[ac].js`: matches both `a` and `c`, returning `['a.js', 'c.js']`
|
376 | - `[b-d].js`: matches from `b` to `d`, returning `['b.js', 'c.js', 'd.js']`
|
377 | - `[b-d].js`: matches from `b` to `d`, returning `['b.js', 'c.js', 'd.js']`
|
378 | - `a/[A-Z].js`: matches and uppercase letter, returning `['a/E.md']`
|
379 |
|
380 | Learn about [regex character classes][character-classes].
|
381 |
|
382 | ### Regex groups
|
383 |
|
384 | Given `['a.js', 'b.js', 'c.js', 'd.js', 'E.js']`:
|
385 |
|
386 | - `(a|c).js`: would match either `a` or `c`, returning `['a.js', 'c.js']`
|
387 | - `(b|d).js`: would match either `b` or `d`, returning `['b.js', 'd.js']`
|
388 | - `(b|[A-Z]).js`: would match either `b` or an uppercase letter, returning `['b.js', 'E.js']`
|
389 |
|
390 | As with regex, parenthese can be nested, so patterns like `((a|b)|c)/b` will work. But it might be easier to achieve your goal using brace expansion.
|
391 |
|
392 | ## Notes
|
393 |
|
394 | Whenever possible parsing behavior for patterns is based on globbing specifications in Bash 4.3. Patterns that aren't described by Bash follow wildmatch spec (used by git).
|
395 |
|
396 |
|
397 | ## Benchmarks
|
398 |
|
399 | Run the [benchmarks](./benchmark):
|
400 |
|
401 | ```bash
|
402 | npm run benchmark
|
403 | ```
|
404 |
|
405 | As of March 26, 2015:
|
406 |
|
407 | ```bash
|
408 | #1: basename-braces.js
|
409 | micromatch.js x 25,776 ops/sec ±0.68% (98 runs sampled)
|
410 | minimatch.js x 3,335 ops/sec ±1.09% (98 runs sampled)
|
411 |
|
412 | #2: basename.js
|
413 | micromatch.js x 24,676 ops/sec ±0.56% (95 runs sampled)
|
414 | minimatch.js x 4,908 ops/sec ±0.95% (97 runs sampled)
|
415 |
|
416 | #3: braces-no-glob.js
|
417 | micromatch.js x 473,492 ops/sec ±0.64% (96 runs sampled)
|
418 | minimatch.js x 27,705 ops/sec ±1.78% (91 runs sampled)
|
419 |
|
420 | #4: braces.js
|
421 | micromatch.js x 42,522 ops/sec ±0.63% (97 runs sampled)
|
422 | minimatch.js x 3,995 ops/sec ±1.36% (95 runs sampled)
|
423 |
|
424 | #5: immediate.js
|
425 | micromatch.js x 24,048 ops/sec ±0.72% (95 runs sampled)
|
426 | minimatch.js x 4,786 ops/sec ±1.40% (95 runs sampled)
|
427 |
|
428 | #6: large.js
|
429 | micromatch.js x 773 ops/sec ±0.62% (98 runs sampled)
|
430 | minimatch.js x 27.52 ops/sec ±0.66% (49 runs sampled)
|
431 |
|
432 | #7: long.js
|
433 | micromatch.js x 7,388 ops/sec ±0.64% (99 runs sampled)
|
434 | minimatch.js x 608 ops/sec ±0.95% (95 runs sampled)
|
435 |
|
436 | #8: mid.js
|
437 | micromatch.js x 41,193 ops/sec ±0.74% (99 runs sampled)
|
438 | minimatch.js x 2,724 ops/sec ±1.09% (97 runs sampled)
|
439 |
|
440 | #9: multi-patterns.js
|
441 | micromatch.js x 12,909 ops/sec ±0.71% (93 runs sampled)
|
442 | minimatch.js x 2,798 ops/sec ±1.45% (95 runs sampled)
|
443 |
|
444 | #10: no-glob.js
|
445 | micromatch.js x 430,787 ops/sec ±0.66% (98 runs sampled)
|
446 | minimatch.js x 47,222 ops/sec ±2.19% (86 runs sampled)
|
447 |
|
448 | #11: range.js
|
449 | micromatch.js x 474,561 ops/sec ±0.69% (97 runs sampled)
|
450 | minimatch.js x 10,819 ops/sec ±2.20% (88 runs sampled)
|
451 |
|
452 | #12: shallow.js
|
453 | micromatch.js x 239,098 ops/sec ±0.67% (96 runs sampled)
|
454 | minimatch.js x 27,782 ops/sec ±2.12% (92 runs sampled)
|
455 |
|
456 | #13: short.js
|
457 | micromatch.js x 707,905 ops/sec ±0.97% (97 runs sampled)
|
458 | minimatch.js x 52,171 ops/sec ±2.45% (84 runs sampled)
|
459 | ```
|
460 |
|
461 | ## Run tests
|
462 | Install dev dependencies:
|
463 |
|
464 | ```bash
|
465 | npm i -d && npm test
|
466 | ```
|
467 |
|
468 | ## Contributing
|
469 | Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/micromatch/issues)
|
470 |
|
471 | Please be sure to run the benchmarks before/after any code changes to judge the impact before you do a PR. thanks!
|
472 |
|
473 | ## Related
|
474 | * [braces](https://github.com/jonschlinkert/braces): Fastest brace expansion for node.js, with the most complete support for the Bash 4.3 braces specification.
|
475 | * [fill-range](https://github.com/jonschlinkert/fill-range): Fill in a range of numbers or letters, optionally passing an increment or multiplier to use.
|
476 | * [expand-range](https://github.com/jonschlinkert/expand-range): Fast, bash-like range expansion. Expand a range of numbers or letters, uppercase or lowercase. See the benchmarks. Used by micromatch.
|
477 | * [parse-glob](https://github.com/jonschlinkert/parse-glob): Parse a glob pattern into an object of tokens.
|
478 | * [is-glob](https://github.com/jonschlinkert/is-glob): Returns `true` if the given string looks like a glob pattern.
|
479 |
|
480 | ## Author
|
481 |
|
482 | **Jon Schlinkert**
|
483 |
|
484 | + [github/jonschlinkert](https://github.com/jonschlinkert)
|
485 | + [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
|
486 |
|
487 | ## License
|
488 | Copyright (c) 2014-2015 Jon Schlinkert
|
489 | Released under the MIT license
|
490 |
|
491 | ***
|
492 |
|
493 | _This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on March 26, 2015._
|
494 |
|
495 | [switch]: #switch-from-minimatch
|
496 | [multimatch]: https://github.com/sindresorhus/multimatch
|
497 | [minimatch]: https://github.com/isaacs/minimatch
|
498 | [brace expansion]: https://github.com/jonschlinkert/braces
|
499 | [braces]: https://github.com/jonschlinkert/braces
|
500 | [bracket expressions]: https://github.com/jonschlinkert/expand-brackets
|
501 | [character-classes]: http://www.regular-expressions.info/charclass.html
|
502 | [expand]: https://github.com/jonschlinkert/micromatch#expand
|
503 | [extended]: http://mywiki.wooledge.org/BashGuide/Patterns#Extended_Globs
|
504 | [extglobs]: https://github.com/jonschlinkert/extglob
|
505 |
|