You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

408 lines
11 KiB

4 years ago
  1. # :rocket: fast-glob
  2. > Is a faster [`node-glob`](https://github.com/isaacs/node-glob) alternative.
  3. ## :bulb: Highlights
  4. * :rocket: Fast by using Streams and Promises. Used [readdir-enhanced](https://github.com/BigstickCarpet/readdir-enhanced) and [micromatch](https://github.com/jonschlinkert/micromatch).
  5. * :beginner: User-friendly, since it supports multiple and negated patterns (`['*', '!*.md']`).
  6. * :vertical_traffic_light: Rational, because it doesn't read excluded directories (`!**/node_modules/**`).
  7. * :gear: Universal, because it supports Synchronous, Promise and Stream API.
  8. * :money_with_wings: Economy, because it provides `fs.Stats` for matched path if you wanted.
  9. ## Donate
  10. If you want to thank me, or promote your Issue.
  11. [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://paypal.me/mrmlnc)
  12. > Sorry, but I have work and support for packages requires some time after work. I will be glad of your support and PR's.
  13. ## Install
  14. ```
  15. $ npm install --save fast-glob
  16. ```
  17. ## Usage
  18. #### Asynchronous
  19. ```js
  20. const fg = require('fast-glob');
  21. fg(['src/**/*.js', '!src/**/*.spec.js']).then((entries) => console.log(entries));
  22. fg.async(['src/**/*.js', '!src/**/*.spec.js']).then((entries) => console.log(entries));
  23. ```
  24. #### Synchronous
  25. ```js
  26. const fg = require('fast-glob');
  27. const entries = fg.sync(['src/**/*.js', '!src/**/*.spec.js']);
  28. console.log(entries);
  29. ```
  30. #### Stream
  31. ```js
  32. const fg = require('fast-glob');
  33. const stream = fg.stream(['src/**/*.js', '!src/**/*.spec.js']);
  34. const entries = [];
  35. stream.on('data', (entry) => entries.push(entry));
  36. stream.once('error', console.log);
  37. stream.once('end', () => console.log(entries));
  38. ```
  39. ## API
  40. ### fg(patterns, [options])
  41. ### fg.async(patterns, [options])
  42. Returns a `Promise` with an array of matching [entries](#entry).
  43. ### fg.sync(patterns, [options])
  44. Returns an array of matching [entries](#entry).
  45. ### fg.stream(patterns, [options])
  46. Returns a [`ReadableStream`](https://nodejs.org/api/stream.html#stream_readable_streams) when the `data` event will be emitted with [`Entry`](#entry).
  47. #### patterns
  48. * Type: `string|string[]`
  49. This package does not respect the order of patterns. First, all the negative patterns are applied, and only then the positive patterns.
  50. #### options
  51. * Type: `Object`
  52. See [options](#options-1) section for more detailed information.
  53. ### fg.generateTasks(patterns, [options])
  54. Return a set of tasks based on provided patterns. All tasks satisfy the `Task` interface:
  55. ```ts
  56. interface Task {
  57. /**
  58. * Parent directory for all patterns inside this task.
  59. */
  60. base: string;
  61. /**
  62. * Dynamic or static patterns are in this task.
  63. */
  64. dynamic: boolean;
  65. /**
  66. * All patterns.
  67. */
  68. patterns: string[];
  69. /**
  70. * Only positive patterns.
  71. */
  72. positive: string[];
  73. /**
  74. * Only negative patterns without ! symbol.
  75. */
  76. negative: string[];
  77. }
  78. ```
  79. ## Entry
  80. The entry which can be a `string` if the [`stats`](#stats) option is disabled, otherwise `fs.Stats` with two additional `path` and `depth` properties.
  81. ## Options
  82. #### cwd
  83. * Type: `string`
  84. * Default: `process.cwd()`
  85. The current working directory in which to search.
  86. #### deep
  87. * Type: `number|boolean`
  88. * Default: `true`
  89. 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.
  90. For example, you have the following tree:
  91. ```
  92. test
  93. └── one
  94. └── two
  95. └── index.js
  96. ```
  97. > :book: If you specify a pattern with some base directory, this directory will not participate in the calculation of the depth of the found directories. Think of it as a `cwd` option.
  98. ```js
  99. fg('test/**', { onlyFiles: false, deep: 0 });
  100. // -> ['test/one']
  101. fg('test/**', { onlyFiles: false, deep: 1 });
  102. // -> ['test/one', 'test/one/two']
  103. fg('**', { onlyFiles: false, cwd: 'test', deep: 0 });
  104. // -> ['one']
  105. fg('**', { onlyFiles: false, cwd: 'test', deep: 1 });
  106. // -> ['one', 'one/two']
  107. ```
  108. #### ignore
  109. * Type: `string[]`
  110. * Default: `[]`
  111. An array of glob patterns to exclude matches.
  112. #### dot
  113. * Type: `boolean`
  114. * Default: `false`
  115. Allow patterns to match filenames starting with a period (files & directories), even if the pattern does not explicitly have a period in that spot.
  116. #### stats
  117. * Type: `boolean`
  118. * Default: `false`
  119. Return `fs.Stats` with two additional `path` and `depth` properties instead of a `string`.
  120. #### onlyFiles
  121. * Type: `boolean`
  122. * Default: `true`
  123. Return only files.
  124. #### onlyDirectories
  125. * Type: `boolean`
  126. * Default: `false`
  127. Return only directories.
  128. #### followSymlinkedDirectories
  129. * Type: `boolean`
  130. * Default: `true`
  131. Follow symlinked directories when expanding `**` patterns.
  132. #### unique
  133. * Type: `boolean`
  134. * Default: `true`
  135. Prevent duplicate results.
  136. #### markDirectories
  137. * Type: `boolean`
  138. * Default: `false`
  139. Add a `/` character to directory entries.
  140. #### absolute
  141. * Type: `boolean`
  142. * Default: `false`
  143. Return absolute paths for matched entries.
  144. > :book: Note that you need to use this option if you want to use absolute negative patterns like `${__dirname}/*.md`.
  145. #### nobrace
  146. * Type: `boolean`
  147. * Default: `false`
  148. Disable expansion of brace patterns (`{a,b}`, `{1..3}`).
  149. #### brace
  150. * Type: `boolean`
  151. * Default: `true`
  152. The [`nobrace`](#nobrace) option without double-negation. This option has a higher priority then `nobrace`.
  153. #### noglobstar
  154. * Type: `boolean`
  155. * Default: `false`
  156. Disable matching with globstars (`**`).
  157. #### globstar
  158. * Type: `boolean`
  159. * Default: `true`
  160. The [`noglobstar`](#noglobstar) option without double-negation. This option has a higher priority then `noglobstar`.
  161. #### noext
  162. * Type: `boolean`
  163. * Default: `false`
  164. Disable extglob support (patterns like `+(a|b)`), so that extglobs are regarded as literal characters.
  165. #### extension
  166. * Type: `boolean`
  167. * Default: `true`
  168. The [`noext`](#noext) option without double-negation. This option has a higher priority then `noext`.
  169. #### nocase
  170. * Type: `boolean`
  171. * Default: `false`
  172. Disable a [case-sensitive](https://en.wikipedia.org/wiki/Case_sensitivity) mode for matching files.
  173. ##### Examples
  174. * File System: `test/file.md`, `test/File.md`
  175. * Case-sensitive for `test/file.*` pattern (`false`): `test/file.md`
  176. * Case-insensitive for `test/file.*` pattern (`true`): `test/file.md`, `test/File.md`
  177. #### case
  178. * Type: `boolean`
  179. * Default: `true`
  180. The [`nocase`](#nocase) option without double-negation. This option has a higher priority then `nocase`.
  181. #### matchBase
  182. * Type: `boolean`
  183. * Default: `false`
  184. 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`.
  185. #### transform
  186. * Type: `Function`
  187. * Default: `null`
  188. Allows you to transform a path or `fs.Stats` object before sending to the array.
  189. ```js
  190. const fg = require('fast-glob');
  191. const entries1 = fg.sync(['**/*.scss']);
  192. const entries2 = fg.sync(['**/*.scss'], { transform: (entry) => '_' + entry });
  193. console.log(entries1); // ['a.scss', 'b.scss']
  194. console.log(entries2); // ['_a.scss', '_b.scss']
  195. ```
  196. If you are using **TypeScript**, you probably want to specify your own type of the returned array.
  197. ```ts
  198. import * as fg from 'fast-glob';
  199. interface IMyOwnEntry {
  200. path: string;
  201. }
  202. const entries: IMyOwnEntry[] = fg.sync<IMyOwnEntry>(['*.md'], {
  203. transform: (entry) => typeof entry === 'string' ? { path: entry } : { path: entry.path }
  204. // Will throw compilation error for non-IMyOwnEntry types (boolean, for example)
  205. });
  206. ```
  207. ## How to exclude directory from reading?
  208. 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.
  209. ```
  210. first/
  211. ├── file.md
  212. └── second
  213. └── file.txt
  214. ```
  215. If you don't want to read the `second` directory, you must write the following pattern: `!**/second` or `!**/second/**`.
  216. ```js
  217. fg.sync(['**/*.md', '!**/second']); // ['first/file.txt']
  218. fg.sync(['**/*.md'], { ignore: '**/second/**' }); // ['first/file.txt']
  219. ```
  220. > :warning: When you write `!**/second/**/*` it means that the directory will be **read**, but all the entries will not be included in the results.
  221. You have to understand that if you write the pattern to exclude directories, then the directory will not be read under any circumstances.
  222. ## How to use UNC path?
  223. You cannot use UNC paths as patterns (due to syntax), but you can use them as `cwd` directory.
  224. ```ts
  225. fg.sync('*', { cwd: '\\\\?\\C:\\Python27' /* or //?/C:/Python27 */ });
  226. fg.sync('Python27/*', { cwd: '\\\\?\\C:\\' /* or //?/C:/ */ });
  227. ```
  228. ## Compatible with `node-glob`?
  229. Not fully, because `fast-glob` does not implement all options of `node-glob`. See table below.
  230. | node-glob | fast-glob |
  231. | :----------: | :-------: |
  232. | `cwd` | [`cwd`](#cwd) |
  233. | `root` | – |
  234. | `dot` | [`dot`](#dot) |
  235. | `nomount` | – |
  236. | `mark` | [`markDirectories`](#markdirectories) |
  237. | `nosort` | – |
  238. | `nounique` | [`unique`](#unique) |
  239. | `nobrace` | [`nobrace`](#nobrace) or [`brace`](#brace) |
  240. | `noglobstar` | [`noglobstar`](#noglobstar) or [`globstar`](#globstar) |
  241. | `noext` | [`noext`](#noext) or [`extension`](#extension) |
  242. | `nocase` | [`nocase`](#nocase) or [`case`](#case) |
  243. | `matchBase` | [`matchbase`](#matchbase) |
  244. | `nodir` | [`onlyFiles`](#onlyfiles) |
  245. | `ignore` | [`ignore`](#ignore) |
  246. | `follow` | [`followSymlinkedDirectories`](#followsymlinkeddirectories) |
  247. | `realpath` | – |
  248. | `absolute` | [`absolute`](#absolute) |
  249. ## Benchmarks
  250. **Tech specs:**
  251. Server: [Vultr Bare Metal](https://www.vultr.com/pricing/baremetal)
  252. * Processor: E3-1270v6 (8 CPU)
  253. * RAM: 32GB
  254. * Disk: SSD
  255. You can see results [here](https://gist.github.com/mrmlnc/f06246b197f53c356895fa35355a367c) for latest release.
  256. ## Related
  257. * [readdir-enhanced](https://github.com/BigstickCarpet/readdir-enhanced) – Fast functional replacement for `fs.readdir()`.
  258. * [globby](https://github.com/sindresorhus/globby) – User-friendly glob matching.
  259. * [node-glob](https://github.com/isaacs/node-glob) – «Standard» glob functionality for Node.js
  260. * [bash-glob](https://github.com/micromatch/bash-glob) – Bash-powered globbing for node.js.
  261. * [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).
  262. * [tiny-glob](https://github.com/terkelg/tiny-glob) – Tiny and extremely fast library to match files and folders using glob patterns.
  263. ## Changelog
  264. See the [Releases section of our GitHub project](https://github.com/mrmlnc/fast-glob/releases) for changelogs for each release version.
  265. ## License
  266. This software is released under the terms of the MIT license.