@bobfrankston/dirutil
v1.6.2
Published
Native C module for directory listing in Node.js
Downloads
1,503
Maintainers
Readme
@bobfrankston/dirutil
A cross-platform native Node.js module for high-performance directory operations written in C++.
⚠️ Important Disclaimers
Personal Use Software: This module was developed for my own specific use cases and workflows. While I've made it available publicly, I make no guarantees about its suitability for your needs, stability, or correctness. Use at your own risk.
Limited Testing:
- The Linux optimizations have been primarily tested on WSL2 with network mounts (9P)
- Native Linux filesystem support has not been extensively tested
- Windows and macOS testing has been limited to my development environment
- I provide no warranty or support - test thoroughly in your environment before production use
No Promises: This is provided "as-is" with no promises of maintenance, bug fixes, or feature additions. If it works for you, great! If not, you're welcome to fork and modify as needed.
Features
- listDirectory - List files and directories with advanced filtering, sorting, and symlink handling
- listRecent - Get the N most recently modified files in a directory
- getDriveInfo - Get filesystem statistics and drive information
- getAllDrives - Enumerate all available drives/mount points
- Type filtering - Include only files, directories, or both
- Smart symlink handling - Follow symlinks with loop detection and invalid link detection
- Filesystem metadata - Dev/inode information for hard link detection and deduplication
- Full TypeScript support with type definitions
- Cross-platform (Windows, Linux, macOS)
- High performance native C++ implementation
- Linux optimization for network filesystems (9P, SMB, NFS)
Installation
npm install @bobfrankston/dirutilUsage
import { listDirectory, listRecent } from '@bobfrankston/dirutil';
// List all files in a directory
const entries = listDirectory('./src', {
includeHidden: false,
stats: true
});
// List only files (exclude directories)
const filesOnly = listDirectory('./src', {
files: true,
directories: false,
sortBy: 'name'
});
// List only directories
const dirsOnly = listDirectory('./src', {
files: false,
directories: true
});
// List files sorted by modification time (most recent first)
const recent = listDirectory('./src', {
sortBy: 'mtime',
sortDirection: 'desc',
stats: true
});
// Handle symlinks - follow them to determine type
const withSymlinks = listDirectory('./src', {
follow: true, // default - follows symlinks to get target type
sortBy: 'name'
});
// Don't follow symlinks
const noFollow = listDirectory('./src', {
follow: false // symlinks marked as neither file nor directory
});
console.log(entries);
// [
// {
// path: './src/index.ts',
// name: 'index.ts',
// isDirectory: false,
// isFile: true,
// isSymlink: false,
// isInvalid: undefined,
// mtime: 1721300000000,
// size: 1024,
// dev: 81,
// ino: 1234567890
// },
// {
// path: './src/link_to_file',
// name: 'link_to_file',
// isDirectory: false,
// isFile: true, // followed to determine type
// isSymlink: true, // but still marked as symlink
// isInvalid: false,
// dev: 81, // shows target's dev/ino when followed
// ino: 9876543210
// },
// ...
// ]
// Get 5 most recent files (listRecent now only returns files)
const recentFiles = listRecent('./src', 5);
console.log(recentFiles);
// [
// {
// path: './src/latest.ts',
// name: 'latest.ts',
// mtime: 1721300000000,
// isDirectory: false,
// isFile: true,
// isSymlink: false,
// dev: 81,
// ino: 1111111111
// },
// ...
// ]
API
listDirectory(path: string, options?: ListDirectoryOptions): DirectoryEntry[]
Lists files and directories in the specified path with advanced filtering and sorting options.
Options:
includeHidden?: boolean- Include hidden files/directories (default: true)stats?: boolean- Include file statistics like mtime, size, dev/ino (default: true)sortBy?: 'none' | 'name' | 'mtime' | 'size'- Sort entries by field (default: 'none')sortDirection?: 'asc' | 'desc'- Sort direction (default: 'asc')files?: boolean- Include files (default: true)directories?: boolean- Include directories (default: true)follow?: boolean- Follow symlinks to determine target type (default: true)
Entry Structure:
{
path: string, // Full path to the entry
name: string, // Filename/directory name
isDirectory: boolean, // True if directory (or symlink to directory when follow: true)
isFile: boolean, // True if file (or symlink to file when follow: true)
isSymlink: boolean, // True if entry is a symlink (regardless of target)
isInvalid?: boolean, // Only set when follow: true - indicates broken/looping symlink
mtime?: number, // Modification time in milliseconds (if stats: true)
size?: number, // File size in bytes (if stats: true, files only)
dev?: number, // Device ID (symlink's own when follow: false, target's when follow: true)
ino?: number // Inode number (symlink's own when follow: false, target's when follow: true)
}Symlink Behavior:
follow: true(default):- Symlinks retain
isSymlink: truebut get target's type (isFile/isDirectory) - Shows destination's dev/ino
- Broken/looping symlinks marked with
isInvalid: true
- Symlinks retain
follow: false:- Symlinks marked as
isSymlink: true, butisFile: falseandisDirectory: false - Shows symlink's own dev/ino (not the target's)
isInvalidflag is NOT set (even for broken links) since we're not attempting to follow them
- Symlinks marked as
- Important: The
isInvalidflag only appears whenfollow: trueand indicates the symlink couldn't be resolved (broken link or loop)
listRecent(path: string, count?: number): RecentEntry[]
Returns the most recently modified files in a directory, sorted by modification time (newest first). Now only returns files - directories are excluded. Follows symlinks by default.
Parameters:
path- Directory path to scancount- Maximum number of files to return (optional, returns all if not specified)
Drive Information APIs
getDriveInfo(path: string): DriveInfo
Get detailed filesystem information for a path.
getAllDrives(): DriveEntry[]
Enumerate all available drives/mount points on the system.
Advanced Usage
Hard Link Detection
const entries = listDirectory('./src');
const hardLinks = new Map();
entries.forEach(entry => {
const key = `${entry.dev}:${entry.ino}`;
if (!hardLinks.has(key)) {
hardLinks.set(key, []);
}
hardLinks.get(key).push(entry);
});
// Find files with multiple hard links
hardLinks.forEach((links, key) => {
if (links.length > 1) {
console.log('Hard links found:', links.map(l => l.path));
}
});Deduplication by Content Identity
const entries = listDirectory('./backup', { files: true, directories: false });
const seen = new Set();
const duplicates = [];
entries.forEach(entry => {
const identity = `${entry.dev}:${entry.ino}`;
if (seen.has(identity)) {
duplicates.push(entry);
} else {
seen.add(identity);
}
});Requirements
- Node.js ≥22.0.0
Note: Pre-compiled binaries are included for most platforms (Windows x64, Linux x64/ARM64), so compilation is typically not required during installation.
Building from Source
Only needed if you want to modify the C++ code or build for unsupported platforms.
Build Requirements
- Python 3 (for node-gyp)
- C++ compiler with C++17 support
- Build tools for your platform:
- Windows: Visual Studio Build Tools or Visual Studio (can build all platforms)
- Linux:
build-essentialpackage,libc6-dev - macOS: Xcode Command Line Tools
Build Commands
npm install # Installs dependencies (uses prebuilt binaries by default)
npm run build:native # Compile native module from source (node-gyp rebuild)
npm run build # Build all: prebuild:all + build:ts
npm run build:ts # Compile TypeScript only
npm run clean # Clean build artifactsCross-Platform Building
Windows can build binaries for all platforms:
npm run prebuild:all # Smart cross-platform build (detects environment)
npm run prebuild:win32:x64 # Windows x64 binary
npm run prebuild:linux:x64 # Linux x64 binary (via WSL)
npm run prebuild:linux:arm64 # Linux ARM64 binary (via WSL)Cross-Platform Notes
- Uses C++17
std::filesystemfor cross-platform file operations - Path separators handled automatically
- File permissions (
modefield) have different meanings on Windows vs Unix systems - Hidden files: Unix uses
.prefix, Windows uses file attributes
