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 🙏

© 2026 – Pkg Stats / Ryan Hefner

ls-json

v1.5.1

Published

parse ls output to json

Readme

ls-json

Zero Dependencies

A powerful TypeScript library to parse ls and ls -R output into structured JSON format with advanced querying capabilities.

✨ Features

  • 🚀 Zero Dependencies - Pure TypeScript implementation with no external dependencies for maximum compatibility and minimal bundle size
  • 📁 Standard ls parsing - Parse regular ls -l output into structured data
  • 🔄 Recursive ls parsing - Parse ls -R output with powerful traversal methods
  • ⚡ Streaming support - Process large ls outputs efficiently
  • 🎯 Advanced querying - Find, filter, and traverse directory structures
  • 🔍 Depth control - Limit recursive parsing depth for performance
  • 🛡️ Error handling - Graceful handling of permission denied and malformed entries

Installation

npm install ls-json

Or using pnpm:

pnpm add ls-json

Quick Start

Basic Usage

import { parse } from "ls-json";

const lsOutput = `total 160
drwxr-xr-x  12 user  staff    384 Sep 19 14:51 .
drwxr-xr-x   9 user  staff    288 Sep 19 14:16 ..
drwxr-xr-x   7 user  staff    224 Sep 19 14:35 dist
-rw-r--r--   1 user  staff   2640 Sep 19 14:51 index.spec.ts`;

const result = parse(lsOutput);
console.log(JSON.stringify(result, null, 2));

Output:

[
  {
    "filename": "dist",
    "flags": "drwxr-xr-x",
    "mode": "755",
    "type": "directory",
    "owner": "user",
    "group": "staff",
    "size": 224,
    "date": "Sep 19 14:35",
    "links": 7
  },
  {
    "filename": "index.spec.ts",
    "flags": "-rw-r--r--",
    "mode": "644",
    "type": "file",
    "owner": "user",
    "group": "staff",
    "size": 2640,
    "date": "Sep 19 14:51",
    "links": 1
  }
]

Recursive Directory Parsing

import { parse } from "ls-json";

const recursiveOutput = `./src:
total 12
-rw-r--r-- 1 user user 256 Sep 19 14:51 index.ts
drwxr-xr-x 2 user user 4096 Sep 19 14:52 utils

./src/utils:
total 8
-rw-r--r-- 1 user user 128 Sep 19 14:53 helper.ts`;

const result = parse(recursiveOutput, { recursive: true });

// Get all files across all directories
const allFiles = result.getAllEntries();
console.log(allFiles.length); // 3 entries

// Find specific files
const indexFile = result.findEntry((entry) => entry.filename === "index.ts");
console.log(indexFile?.parent); // "./src"

// Filter by file type
const jsFiles = result.filterEntries(
  (entry) => entry.filename.endsWith(".ts") && entry.type === "file"
);
console.log(jsFiles.length); // 2 TypeScript files

API Reference

Core Functions

parse(data: string, options?: ParseOptions)

The main parsing function that handles both standard and recursive ls output.

Parameters:

  • data - The ls command output string
  • options - Optional configuration object

Returns:

  • LsEntry[] for standard parsing
  • LsRecursiveOutput for recursive parsing (when options.recursive = true)

parseStreaming(lines: Iterable<string>, options?: ParseOptions)

Process ls output line by line using a generator for memory efficiency.

Parse Options

interface ParseOptions {
  // Parse as recursive ls output (ls -R)
  recursive?: boolean;

  // Maximum directory depth (0 = root only, undefined = no limit)
  depth?: number;

  // Include . and .. entries (default: false)
  showDotsDir?: boolean;

  // Return raw data without processing (default: false)
  raw?: boolean;

  // Continue on errors (default: false)
  ignoreExceptions?: boolean;
}

Recursive Output Methods

When using recursive: true, the result object provides powerful traversal methods:

// Get all entries from all directories
const allEntries = result.getAllEntries();

// Find first entry matching criteria
const configFile = result.findEntry(
  (entry) => entry.filename === "config.json"
);

// Get all entries matching criteria
const largeFiles = result.filterEntries((entry) => entry.size > 1000000);

// Get entries from specific directory
const homeEntries = result.getEntriesByPath("/home/user");

// Get directory tree structure
const tree = result.getDirectoryTree(); // { '/path': [entries...] }

// Process all entries with callback
result.traverse((entry, directory) => {
  console.log(`${directory.path}/${entry.filename}`);
});

Advanced Examples

Depth-Limited Parsing

// Only parse root level + 1 level deep
const result = parse(recursiveOutput, {
  recursive: true,
  depth: 1,
});

// Process shallow structure for better performance
const topLevelDirs = result.filterEntries(
  (entry) => entry.type === "directory"
);

File Analysis

const result = parse(lsRecursiveOutput, { recursive: true });

// Find the largest file
const largestFile = result
  .getAllEntries()
  .filter((entry) => entry.type === "file" && typeof entry.size === "number")
  .reduce((largest, current) =>
    current.size > largest.size ? current : largest
  );

// Count files by extension
const extensionCounts = {};
result.traverse((entry) => {
  if (entry.type === "file") {
    const ext = entry.filename.split(".").pop() || "no-extension";
    extensionCounts[ext] = (extensionCounts[ext] || 0) + 1;
  }
});

// Find executable files
const executables = result.filterEntries(
  (entry) => entry.flags && entry.flags.includes("x") && entry.type === "file"
);

Error Handling

const result = parse(lsOutput, {
  recursive: true,
  ignoreExceptions: true,
});

// Check for parsing errors
if (result.errors) {
  console.log("Global errors:", result.errors);
}

// Check directory-specific errors
result.directories.forEach((dir) => {
  if (dir.errors) {
    console.log(`Errors in ${dir.path}:`, dir.errors);
  }
});

Data Structures

LsEntry

interface LsEntry {
  filename: string; // File or directory name
  flags: string; // Permission string (e.g., "-rwxr-xr-x")
  mode: string; // Octal permissions (e.g., "755")
  type:
    | "file"
    | "directory"
    | "symlink"
    | "block"
    | "character"
    | "pipe"
    | "socket";
  owner: string; // Owner username
  group: string; // Group name
  size: number | string; // Size in bytes or human-readable
  date: string; // Modification date
  links?: number; // Hard link count
  parent?: string; // Parent directory (recursive mode only)
  link_to?: string; // Symlink target
  epoch?: number; // Unix timestamp (when available)
}

Performance Tips

  • Use depth parameter to limit recursive parsing depth
  • Use parseStreaming for very large outputs
  • Set ignoreExceptions: true for malformed input
  • Use specific query methods instead of getAllEntries() when possible

License

Apache-2.0