npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@bobfrankston/dirutil

v1.6.2

Published

Native C module for directory listing in Node.js

Downloads

1,503

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/dirutil

Usage

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: true but get target's type (isFile/isDirectory)
    • Shows destination's dev/ino
    • Broken/looping symlinks marked with isInvalid: true
  • follow: false:
    • Symlinks marked as isSymlink: true, but isFile: false and isDirectory: false
    • Shows symlink's own dev/ino (not the target's)
    • isInvalid flag is NOT set (even for broken links) since we're not attempting to follow them
  • Important: The isInvalid flag only appears when follow: true and 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 scan
  • count - 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-essential package, 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 artifacts

Cross-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::filesystem for cross-platform file operations
  • Path separators handled automatically
  • File permissions (mode field) have different meanings on Windows vs Unix systems
  • Hidden files: Unix uses . prefix, Windows uses file attributes