diff --git a/README.md b/README.md index d7de4f3c..ee810c9c 100644 --- a/README.md +++ b/README.md @@ -1,145 +1,233 @@ -# :rocket: fast-glob +# fast-glob + +> It's a very fast and efficient [glob][glob_definition] library for [Node.js][node_js]. + +This package provides methods for traversing the file system and returning pathnames that matched a defined set of a specified pattern according to the rules used by the Unix Bash shell with some simplifications, meanwhile results are returned in **arbitrary order**. Quick, simple, effective. + +## Table of Contents + +
+Details + +* [Highlights](#highlights) +* [Donation](#donation) +* [Old and modern mode](#old-and-modern-mode) +* [Pattern syntax](#pattern-syntax) + * [Basic syntax](#basic-syntax) + * [Advanced syntax](#advanced-syntax) +* [Installation](#installation) +* [API](#api) + * [Asynchronous](#asynchronous) + * [Synchronous](#synchronous) + * [Stream](#stream) + * [patterns](#patterns) + * [[options]](#options) +* [Options](#options-1) + * [Common](#common) + * [concurrency](#concurrency) + * [cwd](#cwd) + * [deep](#deep) + * [followSymbolicLinks](#followsymboliclinks) + * [fs](#fs) + * [ignore](#ignore) + * [suppressErrors](#suppresserrors) + * [throwErrorOnBrokenSymbolicLink](#throwerroronbrokensymboliclink) + * [Output control](#output-control) + * [absolute](#absolute) + * [markDirectories](#markdirectories) + * [objectMode](#objectmode) + * [onlyDirectories](#onlydirectories) + * [onlyFiles](#onlyfiles) + * [stats](#stats) + * [unique](#unique) + * [Matching control](#matching-control) + * [braceExpansion](#braceexpansion) + * [caseSensitiveMatch](#casesensitivematch) + * [dot](#dot) + * [extglob](#extglob) + * [globstar](#globstar) + * [baseNameMatch](#basenamematch) +* [FAQ](#faq) + * [How to write patterns on Windows?](#how-to-write-patterns-on-windows) + * [Why are parentheses match wrong?](#why-are-parentheses-match-wrong) + * [How to exclude directory from reading?](#how-to-exclude-directory-from-reading) + * [How to use UNC path?](#how-to-use-unc-path) + * [Compatible with `node-glob`?](#compatible-with-node-glob) +* [Benchmarks](#benchmarks) + * [Server](#server) + * [Nettop](#nettop) +* [Changelog](#changelog) +* [License](#license) + +
+ +## Highlights + +* Fast. Probably the fastest. +* Supports multiple and negative patterns. +* Synchronous, Promise and Stream API. +* Object mode. Can return more than just strings. +* Error-tolerant. + +## Donation + +Do you like this project? Support it by donating, creating an issue or pull request. + +[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)][paypal_mrmlnc] + +## Old and modern mode + +This package works in two modes, depending on the environment in which it is used. + +* **Old mode**. Node.js below 10.10 or when the `stats` option is *enabled*. +* **Modern mode**. Node.js 10.10+ and the `stats` option is *disabled*. + +The modern mode is faster. Learn more about the [internal mechanism][nodelib_fs_scandir_old_and_modern_modern]. + +## Pattern syntax + +> :warning: Always use forward-slashes in glob expressions (patterns and [`ignore`](#ignore) option). Use backslashes for escaping characters. + +There is more than one form of syntax: basic and advanced. Below is a brief overview of the supported features. Also pay attention to our [FAQ](#faq). + +> :book: This package uses a [`micromatch`][micromatch] as a library for pattern matching. + +### Basic syntax + +* An asterisk (`*`) — matches everything except slashes (path separators), hidden files (names starting with `.`). +* A double star or globstar (`**`) — matches zero or more directories. +* Question mark (`?`) – matches any single character except slashes (path separators). +* Sequence (`[seq]`) — matches any character in sequence. + +> :book: A few additional words about the [basic matching behavior][picomatch_matching_behavior]. + +Some examples: + +* `src/**/*.js` — matches all files in the `src` directory (any level of nesting) that have the `.js` extension. +* `src/*.??` — matches all files in the `src` directory (only first level of nesting) that have a two-character extension. +* `file-[01].js` — matches files: `file-0.js`, `file-1.js`. + +### Advanced syntax + +* [Escapes characters][micromatch_backslashes] (`\\`) — matching special characters (`$^*+?()[]`) as literals. +* [POSIX character classes][picomatch_posix_brackets] (`[[:digit:]]`). +* [Extended globs][micromatch_extglobs] (`?(pattern-list)`). +* [Bash style brace expansions][micromatch_braces] (`{}`). +* [Regexp character classes][micromatch_regex_character_classes] (`[1-5]`). +* [Regex groups][regular_expressions_brackets] (`(a|b)`). + +> :book: A few additional words about the [advanced matching behavior][micromatch_extended_globbing]. + +Some examples: + +* `src/**/*.{css,scss)` — matches all files in the `src` directory (any level of nesting) that have the `.css` or `.scss` extension. +* `file-[[:digit:]].js` — matches files: `file-0.js`, `file-1.js`, …, `file-9.js`. +* `file-{1..3}.js` — matches files: `file-1.js`, `file-2.js`, `file-3.js`. +* `file-(1|2)` — matches files: `file-1.js`, `file-2.js`. -> Is a faster [`node-glob`](https://github.com/isaacs/node-glob) alternative. +## Installation -## :bulb: Highlights - - * :rocket: Fast by using Streams and Promises. Uses [readdir-enhanced](https://github.com/BigstickCarpet/readdir-enhanced) and [micromatch](https://github.com/jonschlinkert/micromatch). - * :beginner: User-friendly, since it supports multiple and negated patterns (`['*', '!*.md']`). - * :vertical_traffic_light: Rational, because it doesn't read excluded directories (`!**/node_modules/**`). - * :gear: Universal, because it supports Synchronous, Promise and Stream API. - * :money_with_wings: Economy, because it provides `fs.Stats` for matched path if you wanted. - -## Donate - -If you want to thank me, or promote your Issue. - -[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://paypal.me/mrmlnc) +```console +npm install fast-glob +``` -> Sorry, but I have work and support for packages requires some time after work. I will be glad of your support and PR's. +## API -## Install +### Asynchronous +```js +fg(patterns, [options]) ``` -$ npm install --save fast-glob -``` - -## Usage -#### Asynchronous +Returns a `Promise` with an array of matching entries. ```js const fg = require('fast-glob'); -fg(['src/**/*.js', '!src/**/*.spec.js']).then((entries) => console.log(entries)); +const entries = await fg(['.editorconfig', '**/index.js'], { dot: true }); + +// ['.editorconfig', 'services/index.js'] ``` -#### Synchronous +### Synchronous ```js -const fg = require('fast-glob'); - -const entries = fg.sync(['src/**/*.js', '!src/**/*.spec.js']); -console.log(entries); +fg.sync(patterns, [options]) ``` -#### Stream +Returns an array of matching entries. ```js const fg = require('fast-glob'); -const stream = fg.stream(['src/**/*.js', '!src/**/*.spec.js']); +const entries = fg.sync(['.editorconfig', '**/index.js'], { dot: true }); -const entries = []; - -stream.on('data', (entry) => entries.push(entry)); -stream.once('error', console.log); -stream.once('end', () => console.log(entries)); +// ['.editorconfig', 'services/index.js'] ``` -## API - -### fg(patterns, [options]) +### Stream -Returns a `Promise` with an array of matching [entries](#entry). +```js +fg.stream(patterns, [options]) +``` -### fg.sync(patterns, [options]) +Returns a [`ReadableStream`][node_js_stream_readable_streams] when the `data` event will be emitted with matching entry. -Returns an array of matching [entries](#entry). +```js +const fg = require('fast-glob'); -### fg.stream(patterns, [options]) +const stream = fg.sync(['.editorconfig', '**/index.js'], { dot: true }); -Returns a [`ReadableStream`](https://nodejs.org/api/stream.html#stream_readable_streams) when the `data` event will be emitted with [`Entry`](#entry). +for await (const entry of stream) { + // .editorconfig + // services/index.js +} +``` #### patterns - * Type: `string|string[]` - -This package does not respect the order of patterns. First, all the negative patterns are applied, and only then the positive patterns. - -#### options - - * Type: `Object` +* Required: `true` +* Type: `string | string[]` -See [options](#options-1) section for more detailed information. +Any correct pattern(s). -### fg.generateTasks(patterns, [options]) +> :1234: [Pattern syntax](#pattern-syntax) +> +> :warning: This package does not respect the order of patterns. First, all the negative patterns are applied, and only then the positive patterns. If you want to get a certain order of records, use sorting or split calls. -Return a set of tasks based on provided patterns. All tasks satisfy the `Task` interface: +#### [options] -```ts -interface Task { - /** - * Parent directory for all patterns inside this task. - */ - base: string; - /** - * Dynamic or static patterns are in this task. - */ - dynamic: boolean; - /** - * All patterns. - */ - patterns: string[]; - /** - * Only positive patterns. - */ - positive: string[]; - /** - * Only negative patterns without ! symbol. - */ - negative: string[]; -} -``` +* Required: `false` +* Type: [`Options`](#options-1) -## Entry - -The entry which can be a `string` if the [`stats`](#stats) option is disabled, otherwise `fs.Stats` with two additional `path` and `depth` properties. +See [Options](#options-1) section. ## Options +### Common options + #### concurrency - * Type: `number` - * Default: `Infinity` +* Type: `number` +* Default: `Infinity` -The maximum number of concurrent calls to `fs.readdir`. +Specifies the maximum number of concurrent requests from a reader to read directories. -See more more detailed description in the [`fs.walk`](https://github.com/nodelib/nodelib/tree/master/packages/fs/fs.walk#concurrency) repository. +> :book: The higher the number, the higher the performance and load on the file system. If you want to read in quiet mode, set the value to a comfortable number or `4 * os.cpus().length` (4 is default size of [thread pool work scheduling][libuv_threadpool]). #### cwd - * Type: `string` - * Default: `process.cwd()` +* Type: `string` +* Default: `process.cwd()` The current working directory in which to search. #### deep - * Type: `number` - * Default: `Infinity` +* Type: `number` +* Default: `Infinity` -The deep option can be set to `Infinity` to traverse the entire directory structure, or it can be set to a *number* to only traverse that many levels deep. The countdown begins with `1`. +Specifies the maximum depth of a read directory relative to the start directory. For example, you have the following tree: @@ -150,211 +238,309 @@ dir/ └── file.js // 3 ``` -> :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. - ```js -fg('dir/**', { onlyFiles: false, deep: 1 }); -// -> ['dir/one'] -fg('dir/**', { onlyFiles: false, deep: 2 }); -// -> ['dir/one', 'dir/one/two'] +// With base directory +fg.sync('dir/**', { onlyFiles: false, deep: 1 }); // ['dir/one'] +fg.sync('dir/**', { onlyFiles: false, deep: 2 }); // ['dir/one', 'dir/one/two'] + +// With cwd option +fg.sync('**', { onlyFiles: false, cwd: 'dir', deep: 1 }); // ['one'] +fg.sync('**', { onlyFiles: false, cwd: 'dir', deep: 2 }); // ['one', 'one/two'] +``` + +> :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`](#cwd) option. + +#### followSymbolicLinks + +* Type: `boolean` +* Default: `true` -fg('**', { onlyFiles: false, cwd: 'dir', deep: 1 }); -// -> ['one'] -fg('**', { onlyFiles: false, cwd: 'dir', deep: 2 }); -// -> ['one', 'one/two'] +Indicates whether to traverse descendants of symbolic link directories. + +> :book: If the [`stats`](#stats) option is specified, the information about the symbolic link (`fs.lstat`) will be replaced with information about the entry (`fs.stat`) behind it. + +#### fs + +* Type: `FileSystemAdapter` +* Default: `fs.*` + +Custom implementation of methods for working with the file system. + +```ts +export interface FileSystemAdapter { + lstat?: typeof fs.lstat; + stat?: typeof fs.stat; + lstatSync?: typeof fs.lstatSync; + statSync?: typeof fs.statSync; + readdir?: typeof fs.readdir; + readdirSync?: typeof fs.readdirSync; +} ``` #### ignore - * Type: `string[]` - * Default: `[]` +* Type: `string[]` +* Default: `[]` -An array of glob patterns to exclude matches. +An array of glob patterns to exclude matches. This is an alternative way to use negative patterns. -#### dot +```js +dir/ +├── package-lock.json +└── package.json +``` - * Type: `boolean` - * Default: `false` +```js +fg.sync(['*.json', '!package-lock.json']); // ['package.json'] +fg.sync('*.json', { ignore: ['package-lock.json'] }); // ['package.json'] +``` -Allow patterns to match filenames starting with a period (files & directories), even if the pattern does not explicitly have a period in that spot. +#### suppressErrors -#### objectMode +* Type: `boolean` +* Default: `false` - * Type: `boolean` - * Default: `false` +By default this package suppress only `ENOENT` errors. Set to `true` to suppress any error. -Return an [`Entry`](#entry) object instead of filepath. +> :book: Can be useful when the directory has entries with a special level of access. -#### stats +#### throwErrorOnBrokenSymbolicLink - * Type: `boolean` - * Default: `false` +* Type: `boolean` +* Default: `false` -Return `fs.Stats` with two additional `path` and `depth` properties instead of a `string`. +Throw an error when symbolic link is broken if `true` or safely return `lstat` call if `false`. -#### onlyFiles +> :book: This option has no effect on errors when reading the symbolic link directory. - * Type: `boolean` - * Default: `true` +### Output control -Return only files. +#### absolute -#### onlyDirectories +* Type: `boolean` +* Default: `false` - * Type: `boolean` - * Default: `false` +Return the absolute path for entries. -Return only directories. +```js +fg.sync('*.js', { absolute: false }); // ['index.js'] +fg.sync('*.js', { absolute: true }); // ['/home/user/index.js'] +``` -#### followSymbolicLinks +> :book: This option is required if you want to use negative patterns with absolute path, for example, `!${__dirname}/*.js`. - * Type: `boolean` - * Default: `true` +#### markDirectories -Indicates whether to traverse descendants of symbolic link directories. +* Type: `boolean` +* Default: `false` -> :book: Also, if the `stats` option is specified, it tries to get `fs.Stats` for symbolic link file. +Mark the directory path with the final slash. -#### throwErrorOnBrokenSymbolicLink +```js +fs.sync('*', { onlyFiles: false, markDirectories: false }); // ['index.js', 'controllers'] +fs.sync('*', { onlyFiles: false, markDirectories: true }); // ['index.js', 'controllers/'] +``` - * Type: `boolean` - * Default: `true` +#### objectMode -Throw an error when symbolic link is broken if `true` or safely return `lstat` call if `false`. Always `false` when the `stats` option is disabled. +* Type: `boolean` +* Default: `false` -> :book: This option has no effect on errors when reading the symbolic link directory. +Returns objects (instead of strings) describing entries. -#### unique +```js +fg.sync('*', { objectMode: false }); // ['src/index.js'] +fg.sync('*', { objectMode: true }); // [{ name: 'index.js', path: 'src/index.js', dirent: }] +``` - * Type: `boolean` - * Default: `true` +The object has the following fields: -Prevent duplicate results. +* name (`string`) — the last part of the path (basename) +* path (`string`) — full path relative to the pattern base directory +* dirent ([`fs.Dirent`][node_js_fs_class_fs_dirent]) — instance of `fs.Direct` -#### markDirectories +> :book: An object is an internal representation of entry, so getting it does not affect performance. - * Type: `boolean` - * Default: `false` +#### onlyDirectories -Add a `/` character to directory entries. +* Type: `boolean` +* Default: `false` -#### absolute +Return only directories. + +```js +fg.sync('*', { onlyDirectories: false }); // ['index.js', 'src'] +fg.sync('*', { onlyDirectories: true }); // ['src'] +``` - * Type: `boolean` - * Default: `false` +> :book: If `true`, the [`onlyFiles`](#onlyfiles) option is automatically `false`. -Return absolute paths for matched entries. +#### onlyFiles -> :book: Note that you need to use this option if you want to use absolute negative patterns like `${__dirname}/*.md`. +* Type: `boolean` +* Default: `false` -#### braceExpansion +Return only files. - * Type: `boolean` - * Default: `true` +```js +fg.sync('*', { onlyFiles: false }); // ['index.js', 'src'] +fg.sync('*', { onlyFiles: true }); // ['index.js'] +``` -Enable expansion of brace patterns. +#### stats -#### globstar +* Type: `boolean` +* Default: `false` - * Type: `boolean` - * Default: `true` +Enables an [object mode](#objectmode) with an additional field: -Enable matching with globstars (`**`). +* stats ([`fs.Stats`][node_js_fs_class_fs_stats]) — instance of `fs.Stats` -#### extglob +```js +fg.sync('*', { stats: false }); // ['src/index.js'] +fg.sync('*', { stats: true }); // [{ name: 'index.js', path: 'src/index.js', dirent: , stats: }] +``` - * Type: `boolean` - * Default: `true` +> :book: Returns `fs.stat` instead of `fs.lstat` for symbolic links when the [`followSymbolicLinks`](#followsymboliclinks) option is specified. +> +> :warning: Unlike [object mode](#objectmode) this mode requires additional calls to the file system. On average, this mode is slower at least twice. See [old and modern mode](#old-and-modern-mode) for more details. -Enable extglob support, so that extglobs are regarded as literal characters. +#### unique -#### caseSensitiveMatch +* Type: `boolean` +* Default: `true` - * Type: `boolean` - * Default: `true` +Ensures that the returned entries are unique. -Enable a [case-sensitive](https://en.wikipedia.org/wiki/Case_sensitivity) mode for matching files. +```js +fg.sync(['*.json', 'package.json'], { unique: false }); // ['package.json', 'package.json'] +fg.sync(['*.json', 'package.json'], { unique: true }); // ['package.json'] +``` -##### Examples +If `true` and similar entries are found, the result is the first found. -* File System: `test/file.md`, `test/File.md` -* Case-sensitive for `test/file.*` pattern: `test/file.md` -* Case-insensitive for `test/file.*` pattern: `test/file.md`, `test/File.md` +### Matching control -#### baseNameMatch +#### braceExpansion - * Type: `boolean` - * Default: `false` +* Type: `boolean` +* Default: `true` -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`. +Enables Bash-like brace expansion. -> :book: This option has no affect to negative patterns from any source (patterns, `ignore`). +> :1234: [Syntax description][bash_hackers_syntax_expansion_brace] or mode [detailed description][micromatch_braces]. -#### suppressErrors +```js +dir/ +├── abd +├── acd +└── a{b,c}d +``` - * Type: `boolean` - * Default: `false` +```js +fg.sync('a{b,c}d', { braceExpansion: false }); // ['a{b,c}d'] +fg.sync('a{b,c}d', { braceExpansion: true }); // ['abd', 'acd'] +``` -Suppress any errors from reader. Works only with Node.js 10.10+. -Can be useful when the directory has entries with a special level of access. +#### caseSensitiveMatch -#### fs +* Type: `boolean` +* Default: `true` -* Type: `FileSystemAdapter` -* Default: `fs.*` +Enables a [case-sensitive][wikipedia_case_sensitivity] mode for matching files. -Custom implementation of methods for working with the file system. +```js +dir/ +├── file.txt +└── File.txt +``` -```ts -interface FileSystemAdapter { - lstat: typeof fs.lstat; - stat: typeof fs.stat; - lstatSync: typeof fs.lstatSync; - statSync: typeof fs.statSync; - readdir: typeof fs.readdir; - readdirSync: typeof fs.readdirSync; -} +```js +fg.sync('file.txt', { caseSensitiveMatch: false }); // ['file.txt', 'File.txt'] +fg.sync('file.txt', { caseSensitiveMatch: true }); // ['file.txt'] ``` -## How to exclude directory from reading? +#### dot + +* Type: `boolean` +* Default: `false` -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. +Allow patterns to match entries that begin with a period (`.`). +> :book: Note that an explicit dot in a portion of the pattern will always match dot files. + +```js +dir/ +├── .editorconfig +└── package.json ``` -first/ -├── file.md -└── second - └── file.txt + +```js +fg.sync('file.txt', { dot: false }); // ['package.json'] +fg.sync('file.txt', { dot: true }); // ['.editorconfig', 'package.json'] ``` -If you don't want to read the `second` directory, you must write the following pattern: `!**/second` or `!**/second/**`. +#### extglob + +* Type: `boolean` +* Default: `true` + +Enables Bash-like `extglob` functionality. + +> :1234: [Syntax description][micromatch_extglobs]. ```js -fg.sync(['**/*.md', '!**/second']); // ['first/file.md'] -fg.sync(['**/*.md'], { ignore: ['**/second/**'] }); // ['first/file.md'] +dir/ +├── README.md +└── package.json ``` -> :warning: When you write `!**/second/**/*` it means that the directory will be **read**, but all the entries will not be included in the results. +```js +fg.sync('*.+(json|md)', { extglob: false }); // [] +fg.sync('*.+(json|md)', { extglob: true }); // ['README.md', 'package.json'] +``` -You have to understand that if you write the pattern to exclude directories, then the directory will not be read under any circumstances. +#### globstar -## Why are parentheses match wrong? +* Type: `boolean` +* Default: `true` + +Enables recursively repeats a pattern containing `**`. If `false`, `**` behaves exactly like `*`. ```js -fg.sync(['(special-*file).txt']) // → [] for files: ['(special-*file).txt'] +dir/ +└── a + └── b ``` -Refers to Bash. You need to escape special characters: +```js +fg.sync('**', { onlyFiles: false, globstar: false }); // ['a'] +fg.sync('**', { onlyFiles: false, globstar: true }); // ['a', 'a/b'] +``` + +#### baseNameMatch + +* Type: `boolean` +* Default: `false` + +If set to `true`, then patterns without slashes will be matched against the basename of the path if it contains slashes. ```js -fg.sync(['\\(special-*file\\).txt']) // → ['(special-*file).txt'] +dir/ +└── one/ + └── file.md +``` + +```js +fg.sync('*.md', { baseNameMatch: false }); // [] +fg.sync('*.md', { baseNameMatch: true }); // ['one/file.md'] ``` -Read more about [«Matching special characters as literals»](https://github.com/micromatch/picomatch#matching-special-characters-as-literals). +## FAQ ## How to write patterns on Windows? -Always use forward-slashes in glob expressions (patterns and `ignore` option). Use backslashes for escaping characters. With the `cwd` option use a convenient format. +Always use forward-slashes in glob expressions (patterns and [`ignore`](#ignore) option). Use backslashes for escaping characters. With the [`cwd`](#cwd) option use a convenient format. **Bad** @@ -374,13 +560,54 @@ Always use forward-slashes in glob expressions (patterns and `ignore` option). U ] ``` -> :book: Use the [`normalize-path`](https://www.npmjs.com/package/normalize-path) or the [`unixify`](https://www.npmjs.com/package/unixify) package to convert Windows-style path to a Unix-style path. +> :book: Use the [`normalize-path`][npm_normalize_path] or the [`unixify`][npm_unixify] package to convert Windows-style path to a Unix-style path. + +Read more about [matching with backslashes][micromatch_backslashes]. + +## Why are parentheses match wrong? + +```js +dir/ +└── (special-*file).txt +``` + +```js +fg.sync(['(special-*file).txt']) // [] +``` + +Refers to Bash. You need to escape special characters: + +```js +fg.sync(['\\(special-*file\\).txt']) // ['(special-*file).txt'] +``` + +Read more about [matching special characters as literals][picomatch_matching_special_characters_as_literals]. + +## How to exclude directory from reading? + +You can use a negative pattern like this: `!**/node_modules` or `!**/node_modules/**`. Also you can use [`ignore`](#ignore) option. Just look at the example below. + +```js +first/ +├── file.md +└── second/ + └── file.txt +``` + +If you don't want to read the `second` directory, you must write the following pattern: `!**/second` or `!**/second/**`. + +```js +fg.sync(['**/*.md', '!**/second']); // ['first/file.md'] +fg.sync(['**/*.md'], { ignore: ['**/second/**'] }); // ['first/file.md'] +``` + +> :warning: When you write `!**/second/**/*` it means that the directory will be **read**, but all the entries will not be included in the results. -Read more about [matching with backslashes](https://github.com/micromatch/micromatch#backslashes). +You have to understand that if you write the pattern to exclude directories, then the directory will not be read under any circumstances. ## How to use UNC path? -You cannot use UNC paths as patterns (due to syntax), but you can use them as `cwd` directory. +You cannot use [Uniform Naming Convention (UNC)][unc_path] paths as patterns (due to syntax), but you can use them as `cwd` directory. ```ts fg.sync('*', { cwd: '\\\\?\\C:\\Python27' /* or //?/C:/Python27 */ }); @@ -389,8 +616,6 @@ fg.sync('Python27/*', { cwd: '\\\\?\\C:\\' /* or //?/C:/ */ }); ## Compatible with `node-glob`? -Not fully, because `fast-glob` does not implement all options of `node-glob`. See table below. - | node-glob | fast-glob | | :----------: | :-------: | | `cwd` | [`cwd`](#cwd) | @@ -400,42 +625,75 @@ Not fully, because `fast-glob` does not implement all options of `node-glob`. Se | `mark` | [`markDirectories`](#markdirectories) | | `nosort` | – | | `nounique` | [`unique`](#unique) | -| `nobrace` | [`braceExpansion`](#braceExpansion) | +| `nobrace` | [`braceExpansion`](#braceexpansion) | | `noglobstar` | [`globstar`](#globstar) | | `noext` | [`extglob`](#extglob) | -| `nocase` | [`caseSensitiveMatch`](#caseSensitiveMatch) | -| `matchBase` | [`baseNameMatch`](#baseNameMatch) | +| `nocase` | [`caseSensitiveMatch`](#casesensitivematch) | +| `matchBase` | [`baseNameMatch`](#basenamematch) | | `nodir` | [`onlyFiles`](#onlyfiles) | | `ignore` | [`ignore`](#ignore) | -| `follow` | [`followSymbolicLinks`](#followSymbolicLinks) | +| `follow` | [`followSymbolicLinks`](#followsymboliclinks) | | `realpath` | – | | `absolute` | [`absolute`](#absolute) | ## Benchmarks -**Tech specs:** +### Server -Server: [Vultr Bare Metal](https://www.vultr.com/pricing/baremetal) +Link: [Vultr Bare Metal][vultr_pricing_baremetal] - * Processor: E3-1270v6 (8 CPU) - * RAM: 32GB - * Disk: SSD +* Processor: E3-1270v6 (8 CPU) +* RAM: 32GB +* Disk: SSD ([Intel DC S3520 SSDSC2BB240G7][intel_ssd]) -You can see results [here](https://gist.github.com/mrmlnc/f06246b197f53c356895fa35355a367c) for latest release. +You can see results [here][github_gist_benchmark_server] for latest release. -## Related +### Nettop - * [readdir-enhanced](https://github.com/BigstickCarpet/readdir-enhanced) – Fast functional replacement for `fs.readdir()`. - * [globby](https://github.com/sindresorhus/globby) – User-friendly glob matching. - * [node-glob](https://github.com/isaacs/node-glob) – «Standard» glob functionality for Node.js - * [bash-glob](https://github.com/micromatch/bash-glob) – Bash-powered globbing for node.js. - * [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). - * [tiny-glob](https://github.com/terkelg/tiny-glob) – Tiny and extremely fast library to match files and folders using glob patterns. +Link: [Zotac bi323][zotac_bi323] + +* Processor: Intel N3150 (4 CPU) +* RAM: 8GB +* Disk: SSD ([Silicon Power SP060GBSS3S55S25][silicon_power_ssd]) + +You can see results [here][github_gist_benchmark_nettop] for latest release. ## Changelog -See the [Releases section of our GitHub project](https://github.com/mrmlnc/fast-glob/releases) for changelogs for each release version. +See the [Releases section of our GitHub project][github_releases] for changelog for each release version. ## License This software is released under the terms of the MIT license. + +[bash_hackers_syntax_expansion_brace]: https://wiki.bash-hackers.org/syntax/expansion/brace +[github_gist_benchmark_nettop]: https://gist.github.com/mrmlnc/f06246b197f53c356895fa35355a367c#file-fast_glob_benchmark_nettop-txt +[github_gist_benchmark_server]: https://gist.github.com/mrmlnc/f06246b197f53c356895fa35355a367c#file-fast_glob_benchmark_server-txt +[github_releases]: https://github.com/mrmlnc/fast-glob/releases +[glob_definition]: https://en.wikipedia.org/wiki/Glob_(programming) +[glob_linux_man]: http://man7.org/linux/man-pages/man3/glob.3.html +[intel_ssd]: https://ark.intel.com/content/www/us/en/ark/products/93012/intel-ssd-dc-s3520-series-240gb-2-5in-sata-6gb-s-3d1-mlc.html +[libuv_threadpool]: http://docs.libuv.org/en/v1.x/threadpool.html +[micromatch_backslashes]: https://github.com/micromatch/micromatch#backslashes +[micromatch_braces]: https://github.com/micromatch/braces +[micromatch_extended_globbing]: https://github.com/micromatch/micromatch#extended-globbing +[micromatch_extglobs]: https://github.com/micromatch/micromatch#extglobs +[micromatch_regex_character_classes]: https://github.com/micromatch/micromatch#regex-character-classes +[micromatch]: https://github.com/micromatch/micromatch +[node_js_fs_class_fs_dirent]: https://nodejs.org/api/fs.html#fs_class_fs_dirent +[node_js_fs_class_fs_stats]: https://nodejs.org/api/fs.html#fs_class_fs_stats +[node_js_stream_readable_streams]: https://nodejs.org/api/stream.html#stream_readable_streams +[node_js]: https://nodejs.org/en +[nodelib_fs_scandir_old_and_modern_modern]: https://github.com/nodelib/nodelib/blob/master/packages/fs/fs.scandir/README.md#old-and-modern-mode +[npm_normalize_path]: https://www.npmjs.com/package/normalize-path +[npm_unixify]: https://www.npmjs.com/package/unixify +[paypal_mrmlnc]:https://paypal.me/mrmlnc +[picomatch_matching_behavior]: https://github.com/micromatch/picomatch#matching-behavior-vs-bash +[picomatch_matching_special_characters_as_literals]: https://github.com/micromatch/picomatch#matching-special-characters-as-literals +[picomatch_posix_brackets]: https://github.com/micromatch/picomatch#posix-brackets +[regular_expressions_brackets]: https://www.regular-expressions.info/brackets.html +[silicon_power_ssd]: https://www.silicon-power.com/web/product-1 +[unc_path]: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/62e862f4-2a51-452e-8eeb-dc4ff5ee33cc +[vultr_pricing_baremetal]: https://www.vultr.com/pricing/baremetal +[wikipedia_case_sensitivity]: https://en.wikipedia.org/wiki/Case_sensitivity +[zotac_bi323]: https://www.zotac.com/ee/product/mini_pcs/zbox-bi323 diff --git a/package.json b/package.json index 3e7b3b67..2630c8e4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "fast-glob", "version": "2.2.6", - "description": "Is a faster `node-glob` alternative", + "description": "It's a very fast and efficient glob library for Node.js", "license": "MIT", "repository": "mrmlnc/fast-glob", "author": { diff --git a/src/settings.ts b/src/settings.ts index f9166b99..6c474fb4 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -11,97 +11,143 @@ export const DEFAULT_FILE_SYSTEM_ADAPTER: FileSystemAdapter = { readdirSync: fs.readdirSync }; +// tslint:disable no-redundant-jsdoc export interface Options { /** - * The maximum number of concurrent calls to `fs.readdir`. + * Return the absolute path for entries. + * + * @default false */ - concurrency?: number; + absolute?: boolean; /** - * The current working directory in which to search. + * If set to `true`, then patterns without slashes will be matched against + * the basename of the path if it contains slashes. + * + * @default false */ - cwd?: string; + baseNameMatch?: boolean; /** - * 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. + * Enables Bash-like brace expansion. + * + * @default true */ - deep?: number; + braceExpansion?: boolean; /** - * Add an array of glob patterns to exclude matches. + * Enables a case-sensitive mode for matching files. + * + * @default true */ - ignore?: Pattern[]; + caseSensitiveMatch?: boolean; /** - * Allow patterns to match filenames starting with a period (files & directories), - * even if the pattern does not explicitly have a period in that spot. + * Specifies the maximum number of concurrent requests from a reader to read + * directories. + * + * @default Infinity */ - dot?: boolean; + concurrency?: number; /** - * Return `Entry` object instead of filepath. + * The current working directory in which to search. + * + * @default process.cwd() */ - objectMode?: boolean; + cwd?: string; /** - * Return `fs.Stats` with `path` property instead of file path. + * Specifies the maximum depth of a read directory relative to the start + * directory. + * + * @default Infinity */ - stats?: boolean; + deep?: number; /** - * Return only files. + * Allow patterns to match entries that begin with a period (`.`). + * + * @default false */ - onlyFiles?: boolean; + dot?: boolean; /** - * Return only directories. + * Enables Bash-like `extglob` functionality. + * + * @default true */ - onlyDirectories?: boolean; + extglob?: boolean; /** * Indicates whether to traverse descendants of symbolic link directories. - * Also, if the `stats` option is specified, it tries to get `fs.Stats` for symbolic link file. + * + * @default true */ followSymbolicLinks?: boolean; /** - * Throw an error when symbolic link is broken if `true` or safely return `lstat` call if `false`. + * Custom implementation of methods for working with the file system. + * + * @default fs.* */ - throwErrorOnBrokenSymbolicLink?: boolean; + fs?: Partial; /** - * Prevent duplicate results. + * Enables recursively repeats a pattern containing `**`. + * If `false`, `**` behaves exactly like `*`. + * + * @default true */ - unique?: boolean; + globstar?: boolean; /** - * Add a `/` character to directory entries. + * An array of glob patterns to exclude matches. + * This is an alternative way to use negative patterns. + * + * @default [] */ - markDirectories?: boolean; + ignore?: Pattern[]; /** - * Return absolute paths for matched entries. + * Mark the directory path with the final slash. + * + * @default false */ - absolute?: boolean; + markDirectories?: boolean; /** - * Enable expansion of brace patterns. + * Returns objects (instead of strings) describing entries. + * + * @default false */ - braceExpansion?: boolean; + objectMode?: boolean; /** - * Enable matching with globstars (`**`). + * Return only directories. + * + * @default false */ - globstar?: boolean; + onlyDirectories?: boolean; /** - * Enable extglob support, so that extglobs are regarded as literal characters. + * Return only files. + * + * @default true */ - extglob?: boolean; + onlyFiles?: boolean; /** - * Enable a case-sensitive regex for matching files. + * Enables an object mode (`objectMode`) with an additional `stats` field. + * + * @default false */ - caseSensitiveMatch?: boolean; + stats?: boolean; /** - * 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`. + * By default this package suppress only `ENOENT` errors. + * Set to `true` to suppress any error. + * + * @default false */ - baseNameMatch?: boolean; + suppressErrors?: boolean; /** - * Suppress any errors from reader. - * Can be useful when the directory has entries with a special level of access. + * Throw an error when symbolic link is broken if `true` or safely + * return `lstat` call if `false`. + * + * @default false */ - suppressErrors?: boolean; + throwErrorOnBrokenSymbolicLink?: boolean; /** - * Custom implementation of methods for working with the file system. + * Ensures that the returned entries are unique. + * + * @default true */ - fs?: Partial; + unique?: boolean; } +// tslint:enable no-redundant-jsdoc export default class Settings { public readonly absolute: boolean = this._getValue(this._options.absolute, false);