A simple directory tree walker for Node.js with event-driven API
npx @tessl/cli install tessl/npm-walker@1.0.0Walker is a Node.js library that provides asynchronous directory tree traversal with an event-driven API. It broadcasts events for various file types as well as a generic "entry" event for all types and provides the ability to prune directory trees during traversal.
npm install walkerconst Walker = require('walker');const Walker = require('walker');
Walker('/path/to/directory')
.on('file', function(file, stat) {
console.log('Found file: ' + file);
})
.on('dir', function(dir, stat) {
console.log('Found directory: ' + dir);
})
.on('end', function() {
console.log('Directory traversal complete');
});Walker is built around an EventEmitter pattern:
Creates a new directory walker instance and immediately starts traversal.
/**
* Creates a directory walker instance
* @param {string} root - The directory path to start walking from
* @returns {Walker} Walker instance (EventEmitter)
*/
function Walker(root);Usage Examples:
// Constructor with 'new'
const walker = new Walker('/etc');
// Constructor without 'new' (both work identically)
const walker = Walker('/etc');
// Chaining event handlers
Walker('/home/user')
.filterDir(function(dir, stat) {
return dir !== '/home/user/node_modules';
})
.on('file', function(file, stat) {
console.log('File:', file);
});Setup a function to filter out directory entries during traversal.
/**
* Setup a function to filter out directory entries
* @param {function} fn - Filter function that receives (dir, stat) and returns boolean
* @returns {Walker} Walker instance for chaining
*/
Walker.prototype.filterDir(fn);Usage Examples:
// Skip specific directories
Walker('/project')
.filterDir(function(dir, stat) {
if (dir.endsWith('node_modules') || dir.endsWith('.git')) {
return false; // Skip these directories and their children
}
return true; // Include this directory
})
.on('entry', function(entry, stat) {
console.log('Processing:', entry);
});
// Filter based on directory stats
Walker('/logs')
.filterDir(function(dir, stat) {
// Skip directories older than 30 days
const thirtyDaysAgo = Date.now() - (30 * 24 * 60 * 60 * 1000);
return stat.mtime.getTime() > thirtyDaysAgo;
});Walker emits events for different file system entry types encountered during traversal.
Generic event emitted for all file system entries.
/**
* Emitted for every file system entry encountered
* @param {string} entry - Path of the entry
* @param {fs.Stats} stat - File system stats object
*/
walker.on('entry', function(entry, stat) { });Emitted for directory entries.
/**
* Emitted for directory entries
* @param {string} dir - Directory path
* @param {fs.Stats} stat - File system stats object
*/
walker.on('dir', function(dir, stat) { });Emitted for regular file entries.
/**
* Emitted for regular file entries
* @param {string} file - File path
* @param {fs.Stats} stat - File system stats object
*/
walker.on('file', function(file, stat) { });Emitted for symbolic link entries.
/**
* Emitted for symbolic link entries
* @param {string} symlink - Symlink path
* @param {fs.Stats} stat - File system stats object
*/
walker.on('symlink', function(symlink, stat) { });Emitted for block device entries.
/**
* Emitted for block device entries
* @param {string} blockDevice - Block device path
* @param {fs.Stats} stat - File system stats object
*/
walker.on('blockDevice', function(blockDevice, stat) { });Emitted for character device entries.
/**
* Emitted for character device entries
* @param {string} characterDevice - Character device path
* @param {fs.Stats} stat - File system stats object
*/
walker.on('characterDevice', function(characterDevice, stat) { });Emitted for FIFO (named pipe) entries.
/**
* Emitted for FIFO (named pipe) entries
* @param {string} fifo - FIFO path
* @param {fs.Stats} stat - File system stats object
*/
walker.on('fifo', function(fifo, stat) { });Emitted for socket entries.
/**
* Emitted for socket entries
* @param {string} socket - Socket path
* @param {fs.Stats} stat - File system stats object
*/
walker.on('socket', function(socket, stat) { });Emitted when errors occur during traversal.
/**
* Emitted when errors occur during traversal
* @param {Error} error - The error object
* @param {string} entry - Path where error occurred
* @param {fs.Stats|undefined} stat - File system stats object (may be undefined)
*/
walker.on('error', function(error, entry, stat) { });Usage Examples:
Walker('/some/path')
.on('error', function(er, entry, stat) {
console.error('Error processing ' + entry + ':', er.message);
// Continue processing other files
})
.on('end', function() {
console.log('Traversal completed despite errors');
});Emitted when directory traversal is complete.
/**
* Emitted when directory traversal is complete
*/
walker.on('end', function() { });Custom error thrown when file type cannot be determined.
/**
* Error thrown when the type of a file could not be determined
*/
Walker.UnknownFileTypeError;Usage Examples:
Walker('/some/path')
.on('error', function(er, entry, stat) {
if (er instanceof Walker.UnknownFileTypeError) {
console.warn('Unknown file type for:', entry);
} else {
console.error('Other error:', er.message);
}
});const Walker = require('walker');
Walker('/etc/')
.filterDir(function(dir, stat) {
if (dir === '/etc/pam.d') {
console.warn('Skipping /etc/pam.d and children');
return false;
}
return true;
})
.on('entry', function(entry, stat) {
console.log('Got entry: ' + entry);
})
.on('dir', function(dir, stat) {
console.log('Got directory: ' + dir);
})
.on('file', function(file, stat) {
console.log('Got file: ' + file);
})
.on('symlink', function(symlink, stat) {
console.log('Got symlink: ' + symlink);
})
.on('blockDevice', function(blockDevice, stat) {
console.log('Got blockDevice: ' + blockDevice);
})
.on('fifo', function(fifo, stat) {
console.log('Got fifo: ' + fifo);
})
.on('socket', function(socket, stat) {
console.log('Got socket: ' + socket);
})
.on('characterDevice', function(characterDevice, stat) {
console.log('Got characterDevice: ' + characterDevice);
})
.on('error', function(er, entry, stat) {
console.log('Got error ' + er + ' on entry ' + entry);
})
.on('end', function() {
console.log('All files traversed.');
});