npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

find-plus

v2.0.0

Published

A file finding utility patterned after Linux find.

Downloads

7

Readme

find-plus

coverage: 99%

A file finding utility patterned after Linux find.

Install

npm i find-plus

Usage

import { find } from 'find-plus' // ESM
// const { find } = require('find-plus')  // CJS

const isaTXTFile = (f) => f.name.endsWith('.txt')
const files = await find({ onlyFiles: true, root: process.env.HOME, tests: [isaTXTFile] }

console.log(`You have ${files.length} text files under your home directory.`)

Options

find() takes the following options (only the root option is required):

  • Root options:
    • root: (required, string) The directory from which the search begins. May be absolute (starts with '/') or relative to process.cwd().[^1]
    • excludeRoot: (boolean, default: false) If true, the root directory is excluded from the results even if it would otherwise be included.
  • Path matching (see extglob patterns and path matching for efficient searching for additional details):
    • paths: (string[]) If defined, then only matching file paths are included in the results. The path is considered absolute if it starts with '/' and is otherwise relative to root.
    • excludePaths: (string[]) If defined, then any matching file paths are excluded from the results. Matching directories, however, may still be searched; refer to path matching for efficient searching for guidance. Absolute and relative paths handled as with paths.
  • Limiting depth and leaf results:
    • depth: (int) If defined, will only search the specified number of levels below root (which is depth 0). Negatvie values are equivalent to 0.
    • leavesOnly: (boolean, default: false) If true, then limits the results to leaf files at depth. E.g., depth = 0 will match only the root directory and depth = 1 will only match those files within the root directory, and so forth.
  • Selecting files types:[^2]
    • onlyBlockDevices: (boolean, default: false) Include only block devices.
    • onlyCharacterDevices: (boolean, default: false) Include only character devices.
    • onlyDirs: (boolean, default: false) Include only directories.
    • onlyFIFOs: (boolean, default: false) Include only FIFOs/pipes.
    • onlyFiles: (boolean, default: false) Include only regular files.
    • onlySockets: (boolean, default: false) Include only sockets.
    • onlySpecials: (boolean, default: false) Equivalent to noDirs, noFiles, and noSymbolicLinks.
    • onlySymbolicLinks: (boolean, default: false) Include only symbolic links.
    • noBlockDevices: (boolean, default: false) Exclude block devices.
    • noCharacterDevices: (boolean, default: false) Exclude character devices.
    • noDirs: (boolean, default: false) Exclude directories.
    • noFIFOs: (boolean, default: false) Exclude FIFOs/pipes.
    • noFiles: (boolean, default: false) Exclude regular files.
    • noSockets: (boolean, default: false) Exclude sockets.
    • noSpecial: (boolean, default: false) : Equivalent to noBlockDevcies, noCharacterDevices, noFIFOs, and noSockets.
    • noSymbolicLinks: (boolean, default: false) : Exclude symbolic links.
  • tests: (function[]) If defined, then each potential file is passed to each test which must all return true if the file is to be included in the results. Refer to custom tests for additional information.
  • sort: (string, default: 'breadth') Specifies the preferred order of the results. Possible values are 'breadth', 'depth', 'alpha', and 'none'. The 'none' option returns the order in which the files were discovered on disk with no additional sorting. This is generally equivalent to 'breadth', but the order is not guaranteed.

[^1]: Internally root is always converted to an absolute directory using the internal path.resolve() function. [^2]: Setting all the no* or multiple only* file type selectors will result in an error as the search would be trivially empty.

Extglob pattern syntax

Path matching uses glob style pattern matching provided by minimatch. The "path" matched against is the full file path. Note that when matching a directories specifically, you may include the trailing '/' or not. E.g., searching from the root, the directory /user/jane would be matched by '/user/jane', '/user/jane/', '/user/j*', '/user/j*/', and so forth.

Extglob syntax:

  • *: matches any string or nothing except '/' (file separator)
  • **: matches any string or nothing
  • ?: matches one character or nothing
  • [abc]: matches one of the characters
  • [a-z]: matches a character range
  • [[:alpha:]]: matches a POSIX character class
  • {a,b}: matches one of the patterns, separated by commas, equivalent to '@(a|b)'
  • ?(a|b): matches zero or one of the patterns, separated by pipes
  • *(a|b): matches zero or more of the patterns
  • +(a|b): matches one or more of the patterns
  • @(a|b): matches exactly one of the patterns
  • !(a|b): matches anything except the patterns

The 'or' constructs can be combined with other special patterns; e.g., '+([abc]|zz)' would match 'abccba', 'abczzcba'. 'zzzz', but NOT match 'abczcba', 'z', or 'zz'.

Path matching for efficient searches

Note, that when either excludePaths or paths are defined, the algorithm will skip searching impossible directories.[^3] It can therefore be beneficial and result in faster results to define excludePaths or paths where possible, even where not strictly necessary for the logic. Consider using these options to optimize and reduce search times as well as for functional purposes.

[^3]: There are some edge cases where additional directories are searched, but for the most part the logic pretty good about excluding impossible branches from the search.

When using excludePaths, remember that the pattern does not prevent find() from searching within and below the directory unless the patterns ends in '/**'. E.g., excludePaths = ['foo/'] would exclude directory foo/ from the results, but not foo/bar.txt. excludePaths = ['foo/**'] would skip searching foo/ and any sub-directories altogether.

Custom tests

When specifying custom tests, each function takes two arguments: file and options. The file is a is a fs.DirEnt or fs.Stats object[^4] with name, parentPath, absPath, relPath, and depth properties added. The options object a copy of the options object passed to find() with absRoot added for convenience and the tests property removed. The test functions must return true or false to indicate the file in question should be included (if all other requirements are met) or must be excluded from the results, respectively.

[^4]: Both DirEnt and Stat objects provide a matching set of type identifier functions likeisDirectory(), isFIFO(), isSocket(), etc.

The custom tests are executed after all built in requirements (like leavesOnly, paths, onlyFiles, etc.) are satisfied. Recall that all tests must return true for the file to pass, so 'or' logic must be implemented within the tests themselves.