
Research
2025 Report: Destructive Malware in Open Source Packages
Destructive malware is rising across open source registries, using delays and kill switches to wipe code, break builds, and disrupt CI/CD.
Recursive version of fs.readdir. Exposes a stream API (with small RAM & CPU footprint) and a promise API.
npm install readdirp
jsr add jsr:@paulmillr/readdirp
// Use streams to achieve small RAM & CPU footprint.
// 1) Streams example with for-await.
import readdirp from 'readdirp';
for await (const entry of readdirp('.')) {
const {path} = entry;
console.log(`${JSON.stringify({path})}`);
}
// 2) Streams example, non for-await.
// Print out all JS files along with their size within the current folder & subfolders.
import readdirp from 'readdirp';
readdirp('.', {alwaysStat: true, fileFilter: (f) => f.basename.endsWith('.js')})
.on('data', (entry) => {
const {path, stats: {size}} = entry;
console.log(`${JSON.stringify({path, size})}`);
})
// Optionally call stream.destroy() in `warn()` in order to abort and cause 'close' to be emitted
.on('warn', error => console.error('non-fatal error', error))
.on('error', error => console.error('fatal error', error))
.on('end', () => console.log('done'));
// 3) Promise example. More RAM and CPU than streams / for-await.
import { readdirpPromise } from 'readdirp';
const files = await readdirpPromise('.');
console.log(files.map(file => file.path));
// Other options.
import readdirp from 'readdirp';
readdirp('test', {
fileFilter: (f) => f.basename.endsWith('.js'),
directoryFilter: (d) => d.basename !== '.git',
// directoryFilter: (di) => di.basename.length === 9
type: 'files_directories',
depth: 1
});
const stream = readdirp(root[, options]) — Stream API
stream of entry infosfor await (const entry of stream) with node.js 10+ (asyncIterator).on('data', (entry) => {}) entry info for every file / dir.on('warn', (error) => {}) non-fatal Error that prevents a file / dir from being processed. Example: inaccessible to the user.on('error', (error) => {}) fatal Error which also ends the stream. Example: illegal options where passed.on('end') — we are done. Called when all entries were found and no more will be emitted.on('close') — stream is destroyed via stream.destroy().
Could be useful if you want to manually abort even on a non fatal error.
At that point the stream is no longer readable and no more entries, warning or errors are emittedconst entries = await readdirp.promise(root[, options]) — Promise API. Returns a list of entry infos.
First argument is awalys root, path in which to start reading and recursing into subdirectories.
fileFilter: filter to include or exclude files
directoryFilter: filter to include/exclude directories found and to recurse into. Directories that do not pass a filter will not be recursed into.depth: 5: depth at which to stop recursing even if more subdirectories are foundtype: 'files': determines if data events on the stream should be emitted for 'files' (default), 'directories', 'files_directories', or 'all'. Setting to 'all' will also include entries for other types of file descriptors like character devices, unix sockets and named pipes.alwaysStat: false: always return stats property for every file. Default is false, readdirp will return Dirent entries. Setting it to true can double readdir execution time - use it only when you need file size, mtime etc. Cannot be enabled on node <10.10.0.lstat: false: include symlink entries in the stream along with files. When true, fs.lstat would be used instead of fs.statEntryInfoHas the following properties:
path: 'assets/javascripts/react.js': path to the file/directory (relative to given root)fullPath: '/Users/dev/projects/app/assets/javascripts/react.js': full path to the file/directory foundbasename: 'react.js': name of the file/directorydirent: fs.Dirent: built-in dir entry object - only with alwaysStat: falsestats: fs.Stats: built in stat object - only with alwaysStat: truelet {readdirp} = require('readdirp') in common.jshighWaterMark option. Fixes race conditions related to for-await looping.bigint support to stat output on Windows. This is backwards-incompatible for some cases. Be careful. It you use it incorrectly, you'll see "TypeError: Cannot mix BigInt and other types, use explicit conversions".readdirp(options) to readdirp(root, options)entryType option to typeentryType: 'both' to 'files_directories'EntryInfo
stat to stats
alwaysStat: truedirent is emitted instead of stats by default with alwaysStat: falsename to basenameparentDir and fullParentDir propertiesCopyright (c) 2012-2019 Thorsten Lorenz, Paul Miller (https://paulmillr.com)
MIT License, see LICENSE file.
The 'glob' package provides pattern matching functionality to select files in directories. It's similar to readdirp in that it can be used to search for files, but it uses glob patterns instead of providing a stream API or Promise-based interface.
The 'fs-extra' package extends the built-in Node.js 'fs' module with additional file system methods, including recursive directory reading. While it offers similar functionality to readdirp, fs-extra provides a broader set of file system operations, making it more of a general-purpose library.
The 'walk' package is another Node.js module for recursively reading directory contents. It is similar to readdirp but focuses more on event-based directory walking. Compared to readdirp, 'walk' might offer a simpler API for some use cases but lacks the advanced filtering and mapping capabilities.
FAQs
Recursive version of fs.readdir with small RAM & CPU footprint
The npm package readdirp receives a total of 36,525,789 weekly downloads. As such, readdirp popularity was classified as popular.
We found that readdirp demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
Destructive malware is rising across open source registries, using delays and kill switches to wipe code, break builds, and disrupt CI/CD.

Security News
Socket CTO Ahmad Nassri shares practical AI coding techniques, tools, and team workflows, plus what still feels noisy and why shipping remains human-led.

Research
/Security News
A five-month operation turned 27 npm packages into durable hosting for browser-run lures that mimic document-sharing portals and Microsoft sign-in, targeting 25 organizations across manufacturing, industrial automation, plastics, and healthcare for credential theft.