Last active
April 14, 2020 20:26
-
-
Save Phoenix35/b5e742bbba92300d112827a8ecf82376 to your computer and use it in GitHub Desktop.
An extension of getMatchingExt.js to support predicates in general
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| "use strict"; | |
| const fsP = require("fs").promises; | |
| const path = require("path"); | |
| const { cwd, chdir } = process; | |
| const MAX_ARRAY_LENGTH = 2**32 - 1; | |
| /** | |
| * getMatchingFiles - Lazily generates file paths in a given `targetDir` directory matching the predicate | |
| * @param {Path} targetDir - | |
| * @param {Object|String} options - If `options` is a string, it will be used as a string for options.predicate (UTF-8) | |
| * @param {(function|string|array|Set)} options.predicate - Takes a predicate to match the file name against. | |
| * Can also be a string, an array of file names, or a set of file names. | |
| * @param {?string} options.encoding - Defaults to "utf8" | |
| * @param {?number} options.depth - Defaults to MAX_ARRAY_LENGTH | |
| * @return {AsyncIterableIterator<string>} - An async iterable yielding the paths, relative to `targetDir` | |
| */ | |
| async function *getMatchingFiles ( // eslint-disable-line complexity | |
| targetDir, | |
| options, | |
| ) { | |
| let predicate, | |
| encoding, | |
| depth; | |
| if (typeof options === "string") { | |
| predicate = name => name === options; | |
| encoding = "utf-8"; | |
| depth = Number.MAX_SAFE_INTEGER; | |
| } else { | |
| const possiblePredicate = options.predicate; | |
| if (typeof possiblePredicate === "function") | |
| predicate = possiblePredicate; | |
| else if (typeof possiblePredicate === "string") | |
| predicate = name => name === possiblePredicate; | |
| else if (Array.isArray(possiblePredicate)) | |
| predicate = name => possiblePredicate.includes(name); | |
| else if (Object.prototype.toString.call(possiblePredicate) === "[object Set]") | |
| predicate = name => possiblePredicate.has(name); | |
| encoding = options.encoding ?? "utf8"; | |
| const sensibleDepth = options.depth; | |
| depth = (0 < sensibleDepth && sensibleDepth < MAX_ARRAY_LENGTH) | |
| ? sensibleDepth | |
| : MAX_ARRAY_LENGTH; | |
| } | |
| const oldDir = cwd(), | |
| pathsQueue = [["."]]; | |
| try { | |
| chdir(targetDir); | |
| while (pathsQueue.length) { | |
| // Queue in breadth-first traversal implemented via push - shift. | |
| const currentSegments = pathsQueue.shift(), | |
| currentDepth = currentSegments.length, | |
| currentPath = path.join(...currentSegments); | |
| const files = await fsP.readdir( // eslint-disable-line no-await-in-loop | |
| currentPath, | |
| { encoding, | |
| withFileTypes: true }, | |
| ); | |
| for (const file of files) { | |
| const { name } = file; | |
| if (file.isFile() && predicate(name)) | |
| yield path.join(currentPath, name); | |
| else if (file.isDirectory() && currentDepth <= depth) | |
| pathsQueue.push(currentSegments.concat(name)); | |
| } | |
| } | |
| } finally { | |
| chdir(oldDir); | |
| } | |
| } | |
| module.exports = getMatchingFiles; | |
| // Use | |
| const path = require("path"); | |
| const fs = require("fs"); | |
| const getMatchingFiles = require("./path/to/getMatchingFiles"); | |
| // | |
| for await (const pathOfFile of getMatchingFiles(dirPath, fileName)) | |
| fs.unlink(path.join(dirPath, pathOfFile), err => { | |
| if (err) | |
| throw err; | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment