Recursive, synchronous, and fast file system walker
npx @tessl/cli install tessl/npm-klaw-sync@7.0.0Klaw Sync is a fast, synchronous file system walker for Node.js that recursively traverses directories and returns an array of objects containing file paths and their corresponding fs.Stats instances. It is the synchronous counterpart to the popular klaw library.
npm install klaw-syncconst klawSync = require('klaw-sync');ES6 modules:
import klawSync from 'klaw-sync';const klawSync = require('klaw-sync');
// Basic directory traversal
const items = klawSync('/some/directory');
// Returns: [{ path: '/some/directory/file1.txt', stats: fs.Stats }, ...]
// Get only files
const files = klawSync('/some/directory', { nodir: true });
// Get only directories
const dirs = klawSync('/some/directory', { nofile: true });
// Filter results
const jsFiles = klawSync('/project', {
filter: item => item.path.endsWith('.js')
});Recursively walk a directory tree and return all files and directories with their stats.
/**
* Synchronously walk a directory tree
* @param {string} directory - Path to directory to traverse (resolved to absolute path)
* @param {Object} [options] - Configuration options
* @param {boolean} [options.nodir] - Return only files (ignore directories)
* @param {boolean} [options.nofile] - Return only directories (ignore files)
* @param {number} [options.depthLimit=-1] - Number of levels to recurse (-1 for unlimited)
* @param {Object} [options.fs] - Custom fs implementation (defaults to graceful-fs)
* @param {Function} [options.filter] - Filter function to include/exclude items
* @param {boolean} [options.traverseAll] - Traverse all subdirectories regardless of filter
* @param {Array} [ls] - Internal accumulator array (not for public use)
* @returns {Array<Object>} Array of objects with path and stats properties
*/
function klawSync(directory, options, ls);Parameters:
directory (string): The path to the directory to traverse. Will be resolved to an absolute path.options (Object, optional): Configuration options:
nodir (boolean): When true, returns only files and ignores directoriesnofile (boolean): When true, returns only directories and ignores filesdepthLimit (number, default: -1): The number of directory levels to recurse. -1 means unlimited depth. Internally sets rootDepth for depth calculationsfs (Object, default: graceful-fs): Custom filesystem implementation for testing or mockingfilter (Function): Filter function that receives {path, stats} and returns boolean to include/excludetraverseAll (boolean): When true, traverses all subdirectories even if they don't pass the filter. When false (default), filtered-out directories are not exploredls (Array, internal): Internal accumulator array used for recursive calls. Do not provide this parameter in normal usageReturns:
Array of objects with the following structure:
interface WalkItem {
path: string; // Full absolute path to the file or directory
stats: fs.Stats; // Node.js fs.Stats object with file system information
}Important Behavior Notes:
lstatSync() internally - symbolic links are treated as files with their own stats, not their targets. Symlinks are not followed.traverseAll: false (default), directories that don't pass the filter function are not explored. When traverseAll: true, all subdirectories are explored regardless of filter results, but individual items are still subject to filtering for inclusion in results.Usage Examples:
const path = require('path');
const klawSync = require('klaw-sync');
// Basic usage - get all files and directories
const allItems = klawSync('/project');
console.log(allItems);
// [
// { path: '/project/src', stats: Stats { ... } },
// { path: '/project/src/index.js', stats: Stats { ... } },
// { path: '/project/package.json', stats: Stats { ... } }
// ]
// Files only
const files = klawSync('/project', { nodir: true });
// Directories only
const directories = klawSync('/project', { nofile: true });
// Limit depth to 2 levels
const shallow = klawSync('/project', { depthLimit: 2 });
// Filter for JavaScript files only
const jsFiles = klawSync('/project', {
filter: item => path.extname(item.path) === '.js'
});
// Hide hidden files and directories
const visible = klawSync('/project', {
filter: item => {
const basename = path.basename(item.path);
return basename === '.' || basename[0] !== '.';
}
});
// Filter by modification time (with traverseAll to ensure subdirectories are still explored)
const recent = klawSync('/project', {
filter: item => item.stats.mtime.getTime() > Date.now() - 86400000, // 24 hours
traverseAll: true
});
// Using custom fs (useful for testing with memfs)
const { fs: memfs } = require('memfs');
const memItems = klawSync('/virtual/path', { fs: memfs });The function throws standard Node.js filesystem errors:
const klawSync = require('klaw-sync');
try {
const items = klawSync('/some/directory');
console.log(`Found ${items.length} items`);
} catch (error) {
if (error.code === 'ENOENT') {
console.error('Directory does not exist');
} else if (error.code === 'ENOTDIR') {
console.error('Path is not a directory');
} else {
console.error('Error walking directory:', error);
}
}Klaw Sync is optimized for performance and consistently outperforms similar libraries like walk-sync. Benchmark results show approximately 2x faster performance across different directory sizes:
The library uses:
interface WalkOptions {
nodir?: boolean;
nofile?: boolean;
depthLimit?: number;
fs?: FileSystem;
filter?: (item: WalkItem) => boolean;
traverseAll?: boolean;
}
interface WalkItem {
path: string;
stats: fs.Stats;
}
interface FileSystem {
readdirSync(path: string): string[];
lstatSync(path: string): fs.Stats;
}
// Key fs.Stats properties used by klaw-sync and commonly accessed
interface fs.Stats {
isFile(): boolean;
isDirectory(): boolean;
isSymbolicLink(): boolean;
size: number;
mtime: Date; // modification time
ctime: Date; // change time
atime: Date; // access time
birthtime: Date; // creation time
mode: number; // file permissions
uid: number; // user ID
gid: number; // group ID
}