Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@igorskyflyer/recursive-readdir

igorskyflyer121MIT3.0.0TypeScript support: included

📖 Fast, type-safe recursive directory reader for Node.js with depth control, entry filtering, and sync/async APIs. 📁

cross-platform, directory-listing, directory-recursion, directory-traversal, file-listing, file-system, filesystem-utility, filter-directories, filter-files, fs, igor dimitrijević, igorskyflyer, list-directories, list-files, max-depth, nodejs-utility, nodejs, path-utils, read-directory, recursive-directory, recursive-read, trailing-slash

readme

Icon of Recursive ReadDir

Recursive ReadDir

Recursive Directory Reading • Sync And Async Usage • Flexible Filters • Depth Control

📖 Fast, type-safe recursive directory reader for Node.js with depth control, entry filtering, and sync/async APIs. 📁



📃 Table of Contents



🤖 Features

  • 📂 Reads directories recursively with precise depth control
  • 🎯 Filters results by files-only, directories-only, or all entries
  • ⚡ Supports both synchronous and asynchronous operations
  • 🧩 Accepts custom filter functions for advanced selection
  • ✨ Optionally adds trailing slashes to directory paths
  • 🛡️ Skips unreadable entries without stopping traversal
  • 🏗 Provides a fluent class API for easy configuration
  • 💻 Cross-platform paths, powered by uPath

🎯 Motivation

This npm module was built to provide a reliable and efficient way of listing directories while another project was being developed - a Visual Studio Code extension called New Folder, where a custom QuickPick dialog was required to allow the selection of a root directory.


🕵🏼 Usage

Install it by executing any of the following, depending on your preferred package manager:

pnpm add @igorskyflyer/recursive-readdir
yarn add @igorskyflyer/recursive-readdir
npm i @igorskyflyer/recursive-readdir


🤹🏼 API

λ Function-based

async function readDir(directory: string, options: RecursiveDirOptions): Promise<string[]>

Asynchronously gets files/directories inside the given directory.


Params

directory: string - the directory whose files/directories should be listed,

options: RecursiveDirOptions - additional options.


 function readDirSync(directory: string, options: RecursiveDirOptions): string[]

Synchronously gets files/directories inside the given directory.


Params

directory: string - the directory whose files/directories should be listed,

options: RecursiveDirOptions - additional options.


💎 Class-based

For own convenience and code-reuse you can use the class-based approach.

Define the options once and (re)call the readDirSync()/readDir() when needed.


class RecursiveDir

Available methods

function readDirSync(directory: string): string[]

Synchronously gets files/directories inside the given directory.


Params

directory: string - the directory whose files/directories should be listed.


function readDir(directory: string): Promise<string[]>

Asynchronously gets files/directories inside the given directory.


Params

directory: string - the directory whose files/directories should be listed.


function entries(value: Entry): RecursiveDir

Sets the entries property which controls whether to list files-only, directories-only or both (default).

Params value: Entry - a value with three possible values - provided as class consts,

  • Entry.All,
  • Entry.FilesOnly,
  • Entry.DirectoriesOnly.

function maxDepth(value: Depth): RecursiveDir

Sets maxDepth which controls how many child directories' entries are being listed.


Params

value: Depth - the new maxDepth value.


You can use the 2 predefined values or use an arbitrary value. The predefined values are as follows:

  • Depth.All = -1 - return all subdirectories entries,
  • Depth.Root = 0 (default) - return only root directory's entries.

ℹ️ NOTE

Why the default value of maxDepth is NOT Depth.All?

It is simple: the value must be explicitly set, since traversal through all child subdirectories is highly resource‑ and time‑consuming. For example, if the directory parameter were set to the root of a drive in combination with maxDepth = Depth.All, the operation could become extremely heavy.


To use arbitrary values the provided value parameter must comply with the expression maxDepth >= Depth.Root i.e., maxDepth >= 0.

The value of 0 means that only directory entries found in the directory specified when calling either readDir() or readDirSync() methods are returned. By increasing the number we can set the depth/level of subdirectories that the method should return, e.g.


maxDepth = Depth.Root

maxDepth(Depth.Root)
// return only the files/directories in the current directory

maxDepth = 3

maxDepth(3)
// return the files/directories in the current director files/directories 3-levels deep

maxDepth = Depth.All

maxDepth(Depth.All)
// return all child files/directories in the current directory


function filter(value: FilterCallback): RecursiveDir

Sets filter predicate function used for filtering directory entries (directories/files).


Params

value: FilterCallback - the filter function to use when filtering directory entries.



function addTrailingSlash(value: boolean): RecursiveDir

Sets whether a trailing slash should be added to directory entries.


Params

value: boolean - a Boolean indicating whether a trailing slash should be added to directory entries.



🗒️ Examples

import { readDirSync, Depth, Entry, RecursiveDir } from '@igorskyflyer/recursive-readdir'
const testingPath: string = './somePath'

// Function-based approach

console.log(readDirSync('non-existent-directory')) // returns []

console.log(
  readDirSync(testingPath, {
    maxDepth: Depth.All,
    filter: (entry) => entry.isDirectory,
  })
) // returns only subdirectories (all subdirectories)

// the following can be used interchangeably
console.log(
  readDirSync(testingPath, {
    maxDepth: Depth.All,
    entries: Entry.DirectoriesOnly,
  })
) // returns only subdirectories (all subdirectories)

console.log(
  readDirSync(testingPath, {
    maxDepth: Depth.All,
    entries: Entry.FilesOnly,
    filter: (entry) => entry.path.indexOf('.js') > -1,
  })
) // returns only JavaScript - .js files found in all (sub)directories

// Class-based approach

const dir: RecursiveDir = new RecursiveDir()

dir
  .maxDepth(Depth.All)
  .entries(Entry.FilesOnly)
  .filter((entry) => entry.path.indexOf('.md') > -1)

console.log(dir.readDirSync(testingPath)) // returns only .md (Markdown) files found in all (sub)directories


📝 Changelog

📑 Read about the latest changes in the CHANGELOG.md.



🪪 License

Licensed under the MIT license.



💖 Support

I work hard for every project, including this one and your support means a lot to me!
Consider buying me a coffee. ☕

Donate to igorskyflyer

Thank you for supporting my efforts! 🙏😊


@igorskyflyer/unc-path

🥽 Provides ways of parsing UNC paths and checking whether they are valid. 🎱


@igorskyflyer/comment-it

📜 Formats the provided string as a comment, either a single or a multi line comment for the given programming language. 💻


@igorskyflyer/strip-html

🥞 Removes HTML code from the given string. Can even extract text-only from the given an HTML string. ✨


@igorskyflyer/upath

🎍 Provides a universal way of formatting file-paths in Unix-like and Windows operating systems as an alternative to the built-in path.normalize(). 🧬


@igorskyflyer/valid-path

🧰 Determines whether a given value can be a valid file/directory name. 🏜


👨🏻‍💻 Author

Created by Igor Dimitrijević (@igorskyflyer).

changelog