1 | # :rocket: fast-glob
|
2 |
|
3 | > Is a faster [`node-glob`](https://github.com/isaacs/node-glob) alternative.
|
4 |
|
5 | [![Build Status](https://travis-ci.org/mrmlnc/fast-glob.svg?branch=master)](https://travis-ci.org/mrmlnc/fast-glob)
|
6 | [![Build status](https://ci.appveyor.com/api/projects/status/i4xqijtq26qf6o9d?svg=true)](https://ci.appveyor.com/project/mrmlnc/fast-glob)
|
7 |
|
8 | ## :bulb: Highlights
|
9 |
|
10 | * :rocket: Fast by using Streams and Promises. Used [readdir-enhanced](https://github.com/BigstickCarpet/readdir-enhanced) and [micromatch](https://github.com/jonschlinkert/micromatch).
|
11 | * :beginner: User-friendly, since it supports multiple and negated patterns (`['*', '!*.md']`).
|
12 | * :vertical_traffic_light: Rational, because it doesn't read excluded directories (`!**/node_modules/**`).
|
13 | * :gear: Universal, because it supports Synchronous, Promise and Stream API.
|
14 | * :money_with_wings: Economy, because it provides `fs.Stats` for matched path if you wanted.
|
15 |
|
16 | ## Donate
|
17 |
|
18 | If you want to thank me, or promote your Issue.
|
19 |
|
20 | [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://paypal.me/mrmlnc)
|
21 |
|
22 | > Sorry, but I have work and support for packages requires some time after work. I will be glad of your support and PR's.
|
23 |
|
24 | ## Install
|
25 |
|
26 | ```
|
27 | $ npm install --save fast-glob
|
28 | ```
|
29 |
|
30 | ## Usage
|
31 |
|
32 | #### Asynchronous
|
33 |
|
34 | ```js
|
35 | const fg = require('fast-glob');
|
36 |
|
37 | fg(['src/**/*.js', '!src/**/*.spec.js']).then((entries) => console.log(entries));
|
38 | fg.async(['src/**/*.js', '!src/**/*.spec.js']).then((entries) => console.log(entries));
|
39 | ```
|
40 |
|
41 | #### Synchronous
|
42 |
|
43 | ```js
|
44 | const fg = require('fast-glob');
|
45 |
|
46 | const entries = fg.sync(['src/**/*.js', '!src/**/*.spec.js']);
|
47 | console.log(entries);
|
48 | ```
|
49 |
|
50 | #### Stream
|
51 |
|
52 | ```js
|
53 | const fg = require('fast-glob');
|
54 |
|
55 | const stream = fg.stream(['src/**/*.js', '!src/**/*.spec.js']);
|
56 |
|
57 | const entries = [];
|
58 |
|
59 | stream.on('data', (entry) => entries.push(entry));
|
60 | stream.once('error', console.log);
|
61 | stream.once('end', () => console.log(entries));
|
62 | ```
|
63 |
|
64 | ## API
|
65 |
|
66 | ### fg(patterns, [options])
|
67 | ### fg.async(patterns, [options])
|
68 |
|
69 | Returns a `Promise<Array>` of matching entries.
|
70 |
|
71 | #### patterns
|
72 |
|
73 | * Type: `string|string[]`
|
74 |
|
75 | This package does not respect the order of patterns. First, all the negative patterns are applied, and only then the positive patterns.
|
76 |
|
77 | #### options
|
78 |
|
79 | * Type: `Object`
|
80 |
|
81 | See [options](#options-1) section for more detailed information.
|
82 |
|
83 | ### fg.sync(patterns, [options])
|
84 |
|
85 | Returns a `Array` of matching entries.
|
86 |
|
87 | ### fg.stream(patterns, [options])
|
88 |
|
89 | Returns a [`ReadableStream`](https://nodejs.org/api/stream.html#stream_readable_streams).
|
90 |
|
91 | ### fg.generateTasks(patterns, [options])
|
92 |
|
93 | Return a set of tasks based on provided patterns. All tasks satisfy the `Task` interface:
|
94 |
|
95 | ```ts
|
96 | interface Task {
|
97 | /**
|
98 | * Parent directory for all patterns inside this task.
|
99 | */
|
100 | base: string;
|
101 | /**
|
102 | * Dynamic or static patterns are in this task.
|
103 | */
|
104 | dynamic: boolean;
|
105 | /**
|
106 | * All patterns.
|
107 | */
|
108 | patterns: string[];
|
109 | /**
|
110 | * Only positive patterns.
|
111 | */
|
112 | positive: string[];
|
113 | /**
|
114 | * Only negative patterns without ! symbol.
|
115 | */
|
116 | negative: string[];
|
117 | }
|
118 | ```
|
119 |
|
120 | ## Options
|
121 |
|
122 | #### cwd
|
123 |
|
124 | * Type: `string`
|
125 | * Default: `process.cwd()`
|
126 |
|
127 | The current working directory in which to search.
|
128 |
|
129 | #### deep
|
130 |
|
131 | * Type: `number|boolean`
|
132 | * Default: `true`
|
133 |
|
134 | The deep option can be set to `true` to traverse the entire directory structure, or it can be set to a *number* to only traverse that many levels deep.
|
135 |
|
136 | #### ignore
|
137 |
|
138 | * Type: `string[]`
|
139 | * Default: `[]`
|
140 |
|
141 | An array of glob patterns to exclude matches.
|
142 |
|
143 | #### dot
|
144 |
|
145 | * Type: `boolean`
|
146 | * Default: `false`
|
147 |
|
148 | Allow patterns to match filenames starting with a period (files & directories), even if the pattern does not explicitly have a period in that spot.
|
149 |
|
150 | #### stats
|
151 |
|
152 | * Type: `number|boolean`
|
153 | * Default: `false`
|
154 |
|
155 | Return `fs.Stats` with `path` property instead of file path.
|
156 |
|
157 | #### onlyFiles
|
158 |
|
159 | * Type: `boolean`
|
160 | * Default: `true`
|
161 |
|
162 | Return only files.
|
163 |
|
164 | #### onlyDirectories
|
165 |
|
166 | * Type: `boolean`
|
167 | * Default: `false`
|
168 |
|
169 | Return only directories.
|
170 |
|
171 | #### followSymlinkedDirectories
|
172 |
|
173 | * Type: `boolean`
|
174 | * Default: `true`
|
175 |
|
176 | Follow symlinked directories when expanding `**` patterns.
|
177 |
|
178 | #### unique
|
179 |
|
180 | * Type: `boolean`
|
181 | * Default: `true`
|
182 |
|
183 | Prevent duplicate results.
|
184 |
|
185 | #### markDirectories
|
186 |
|
187 | * Type: `boolean`
|
188 | * Default: `false`
|
189 |
|
190 | Add a `/` character to directory entries.
|
191 |
|
192 | #### absolute
|
193 |
|
194 | * Type: `boolean`
|
195 | * Default: `false`
|
196 |
|
197 | Return absolute paths for matched entries.
|
198 |
|
199 | #### nobrace
|
200 |
|
201 | * Type: `boolean`
|
202 | * Default: `false`
|
203 |
|
204 | Disable expansion of brace patterns (`{a,b}`, `{1..3}`).
|
205 |
|
206 | #### brace
|
207 |
|
208 | * Type: `boolean`
|
209 | * Default: `true`
|
210 |
|
211 | The [`nobrace`](#nobrace) option without double-negation. This option has a higher priority then `nobrace`.
|
212 |
|
213 | #### noglobstar
|
214 |
|
215 | * Type: `boolean`
|
216 | * Default: `false`
|
217 |
|
218 | Disable matching with globstars (`**`).
|
219 |
|
220 | #### globstar
|
221 |
|
222 | * Type: `boolean`
|
223 | * Default: `true`
|
224 |
|
225 | The [`noglobstar`](#noglobstar) option without double-negation. This option has a higher priority then `noglobstar`.
|
226 |
|
227 | #### noext
|
228 |
|
229 | * Type: `boolean`
|
230 | * Default: `false`
|
231 |
|
232 | Disable extglob support (patterns like `+(a|b)`), so that extglobs are regarded as literal characters.
|
233 |
|
234 | #### extension
|
235 |
|
236 | * Type: `boolean`
|
237 | * Default: `true`
|
238 |
|
239 | The [`noext`](#noext) option without double-negation. This option has a higher priority then `noext`.
|
240 |
|
241 | #### nocase
|
242 |
|
243 | * Type: `boolean`
|
244 | * Default: `false`
|
245 |
|
246 | Disable a case-insensitive regex for matching files.
|
247 |
|
248 | #### case
|
249 |
|
250 | * Type: `boolean`
|
251 | * Default: `true`
|
252 |
|
253 | The [`nocase`](#nocase) option without double-negation. This option has a higher priority then `nocase`.
|
254 |
|
255 | #### matchBase
|
256 |
|
257 | * Type: `boolean`
|
258 | * Default: `false`
|
259 |
|
260 | Allow glob patterns without slashes to match a file path based on its basename. For example, `a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`.
|
261 |
|
262 | #### transform
|
263 |
|
264 | * Type: `Function`
|
265 | * Default: `null`
|
266 |
|
267 | Allows you to transform a path or `fs.Stats` object before sending to the array.
|
268 |
|
269 | ```js
|
270 | const fg = require('fast-glob');
|
271 |
|
272 | const entries1 = fg.sync(['**/*.scss']);
|
273 | const entries2 = fg.sync(['**/*.scss'], { transform: (entry) => '_' + entry });
|
274 |
|
275 | console.log(entries1); // ['a.scss', 'b.scss']
|
276 | console.log(entries2); // ['_a.scss', '_b.scss']
|
277 | ```
|
278 |
|
279 | If you are using **TypeScript**, you probably want to specify your own type of the returned array.
|
280 |
|
281 | ```ts
|
282 | import * as fg from 'fast-glob';
|
283 |
|
284 | interface IMyOwnEntry {
|
285 | path: string;
|
286 | }
|
287 |
|
288 | const entries: IMyOwnEntry[] = fg.sync<IMyOwnEntry>(['*.md'], {
|
289 | transform: (entry) => typeof entry === 'string' ? { path: entry } : { path: entry.path }
|
290 | // Will throw compilation error for non-IMyOwnEntry types (boolean, for example)
|
291 | });
|
292 | ```
|
293 |
|
294 | ## How to exclude directory from reading?
|
295 |
|
296 | You can use a negative pattern like this: `!**/node_modules` or `!**/node_modules/**`. Also you can use `ignore` option. Just look at the example below.
|
297 |
|
298 | ```
|
299 | first/
|
300 | ├── file.md
|
301 | └── second
|
302 | └── file.txt
|
303 | ```
|
304 |
|
305 | If you don't want to read the `second` directory, you must write the following pattern: `!**/second` or `!**/second/**`.
|
306 |
|
307 | ```js
|
308 | fg.sync(['**/*.md', '!**/second']); // ['first/file.txt']
|
309 | fg.sync(['**/*.md'], { ignore: '**/second/**' }); // ['first/file.txt']
|
310 | ```
|
311 |
|
312 | > :warning: When you write `!**/second/**/*` it means that the directory will be **read**, but all the entries will not be included in the results.
|
313 |
|
314 | You have to understand that if you write the pattern to exclude directories, then the directory will not be read under any circumstances.
|
315 |
|
316 | ## Compatible with `node-glob`?
|
317 |
|
318 | Not fully, because `fast-glob` does not implement all options of `node-glob`. See table below.
|
319 |
|
320 | | node-glob | fast-glob |
|
321 | | :----------: | :-------: |
|
322 | | `cwd` | [`cwd`](#cwd) |
|
323 | | `root` | – |
|
324 | | `dot` | [`dot`](#dot) |
|
325 | | `nomount` | – |
|
326 | | `mark` | [`markDirectories`](#markdirectories) |
|
327 | | `nosort` | – |
|
328 | | `nounique` | [`unique`](#unique) |
|
329 | | `nobrace` | [`nobrace`](#nobrace) or [`brace`](#brace) |
|
330 | | `noglobstar` | [`noglobstar`](#noglobstar) or [`globstar`](#globstar) |
|
331 | | `noext` | [`noext`](#noext) or [`extension`](#extension) |
|
332 | | `nocase` | [`nocase`](#nocase) or [`case`](#case) |
|
333 | | `matchBase` | [`matchbase`](#matchbase) |
|
334 | | `nodir` | [`onlyFiles`](#onlyfiles) |
|
335 | | `ignore` | [`ignore`](#ignore) |
|
336 | | `follow` | [`followSymlinkedDirectories`](#followsymlinkeddirectories) |
|
337 | | `realpath` | – |
|
338 | | `absolute` | [`absolute`](#absolute) |
|
339 |
|
340 | ## Benchmarks
|
341 |
|
342 | **Tech specs:**
|
343 |
|
344 | Server: [Vultr Bare Metal](https://www.vultr.com/pricing/baremetal)
|
345 |
|
346 | * Processor: E3-1270v6 (8 CPU)
|
347 | * RAM: 32GB
|
348 | * Disk: SSD
|
349 |
|
350 | You can see results [here](https://gist.github.com/mrmlnc/f06246b197f53c356895fa35355a367c) for latest release.
|
351 |
|
352 | ## Related
|
353 |
|
354 | * [readdir-enhanced](https://github.com/BigstickCarpet/readdir-enhanced) – Fast functional replacement for `fs.readdir()`.
|
355 | * [globby](https://github.com/sindresorhus/globby) – User-friendly glob matching.
|
356 | * [node-glob](https://github.com/isaacs/node-glob) – «Standard» glob functionality for Node.js
|
357 | * [bash-glob](https://github.com/micromatch/bash-glob) – Bash-powered globbing for node.js.
|
358 | * [glob-stream](https://github.com/gulpjs/glob-stream) – A Readable Stream interface over node-glob that used in the [gulpjs](https://github.com/gulpjs/gulp).
|
359 |
|
360 | ## Changelog
|
361 |
|
362 | See the [Releases section of our GitHub project](https://github.com/mrmlnc/fast-glob/releases) for changelogs for each release version.
|
363 |
|
364 | ## License
|
365 |
|
366 | This software is released under the terms of the MIT license.
|