Skip to main content

ndx

A static HTML directory index generator.

ndx is a command-line utility for generating index files for directories. It supports file annotations via a JSON configuration file.

Installation

pipx install ndx

Usage

To generate an index in a specific directory, use:

ndx /path/to/directory

Generate index files recursively:

ndx --recursive /path/to/directory

Options

usage: ndx [-h] [-r] [--explicit] [--max-depth MAX_DEPTH] [--max-files MAX_FILES] [--timeout TIMEOUT] [-f] [-v] [--version]
        directory

Builds index for directories. Annotates the index with data from .ndx.json file.

positional arguments:
directory             path to the target directory

options:
-h, --help            show this help message and exit
-r, --recursive       build index files recursively (default: False)
--explicit            explicitly link to index.html files when linking to directories (default: False)
--max-depth MAX_DEPTH
                        maximum recursion depth (levels below the target directory) for building index files (default: 50)
--max-files MAX_FILES
                        maximum number of entries to process for each index (default: 10000)
--timeout TIMEOUT     timeout for symlink stat and path resolution while processing files for the index (in seconds) (default:
                        10)
-f, --force           overwrite existing index.html file(s) (default: False)
-v, --verbose         enable verbose logging (default: False)
--version             show program's version number and exit

Configuration

To customize the index by adding descriptions to the page and files, place a .ndx.json file in the target directory. In recursive mode, each subdirectory needs its own .ndx.json file.

Schema

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "properties": {
        "page": {
            "type": "object",
            "properties": {
                "description": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 10000
                }
            },
            "required": ["description"],
            "additionalProperties": false
        },
        "files": {
            "type": "array",
            "minItems": 1,
            "maxItems": 10000,
            "items": {
                "type": "object",
                "properties": {
                    "name_regex": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 200,
                        "format": "re2-pattern"
                    },
                    "description": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 1000
                    },
                },
                "required": ["name_regex", "description"],
                "additionalProperties": false
            }
        }
    },
    "required": ["page"],
    "additionalProperties": false
}

Examples

{
  "page": {
    "description": "Index page with minimal config file (no file-level description)."
  }
}
{
    "page": {
    "description": "Index page with description and a <a href='https://example.com'>link</a>."
    },
    "files": [
    {
        "name_regex": ".*\\.pdf$",
        "description": "File descriptions can also have <a href='https://example.com'>links</a>"
    },
    {
        "name_regex": "\\.tar",
        "description": "Regex patterns do not need to match the full file name. For example, this description will be applied to both *.tar and *.tar.gz files."
    }
    ]
}

Design Choices and Limitations

  • Script is only tested with currently supported Python versions.

  • Functionality is only guaranteed on POSIX-compliant Unix-like systems.

  • The target directory can be passed to this script via a symlink.

  • Support for hardlinks on the filesystem containing the target directory is required unless the --force option is used.

  • The index files may lose their former ownership and attributes when regenerated.

  • Hidden files (starting with .) and the index file index.html are skipped.

  • Symlinks pointing outside the directory [or subdirectory] being indexed are skipped.

  • Special files (FIFOs, sockets, devices) are skipped.

  • If there are more than --max-files in a directory to process, only --max-files entries in filesystem enumeration order are processed to prevent resource exhaustion.

  • .ndx.json file cannot be a symlink.

  • .ndx.json file size is limited to a maximum of 1M (1,048,576) characters.

  • In recursive mode, each subdirectory needs its own .ndx.json file.

  • Only RE2 regexes are supported.

  • A warning is issued and notes are skipped for files that match multiple regexes.

  • If .ndx.json file does not conform to the schema, it is completely ignored.

  • Descriptions only support HTML anchor tags (<a href=''>...</a>).

  • Only HTTPS links are supported in the descriptions.

  • All attributes except the href are stripped from the HTML anchor tags, and target="_blank" rel="noopener noreferrer nofollow" is added to them.

  • Malformed HTML descriptions may lose some of their content during processing.

  • If the output file is not created for any reason, such as permission errors, exceeding the recursion depth limit, or the existence of an index file, the script exits with a non-zero status code.

  • Failure to access file attributes for indexing is logged, but it has no effect on the script exit code.

History

This script was originally developed for the linkmedic project.

License

  • Copyright 2025-2026 M. Farzalipour Tabriz, Max Planck Institute for Physics (MPP)

All rights reserved.

This software may be modified and distributed under the terms of the GPL-3.0 (or later) License. See the LICENSE file for details.

Release files for ndx 0.6.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ndx 0.6.1
File Size Uploaded
ndx-0.6.1.tar.gz 24.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ndx 0.6.1
File Interpreter ABI Platform
ndx-0.6.1-py3-none-any.whl Python 3 none any Details

Total release size: 49.0 kB

Release files / ndx-0.6.1.tar.gz

Download URL ndx-0.6.1.tar.gz
Size 24.7 kB
Tags Source
SHA-256 checksum
How to use checksums
8a2672e6dc3b50472a68be8882d7b8b67170b2dec5ce7372495e1ea04bb35b5e
BLAKE2b-256 checksum
How to use checksums
a2821f169b1164d78244e26cfd7d1b180dde16ffc3f2c250e4ca394c74b05843
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / ndx-0.6.1-py3-none-any.whl

Download URL ndx-0.6.1-py3-none-any.whl
Size 24.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9f2de095f0104014332edc36205a66f31eda5ffe57367d9a478917a8eba39982
BLAKE2b-256 checksum
How to use checksums
bf3ae0c1342980c64ddffd9c6aa85f85c2a41047c43b9653b18592acea917ac8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.6.1 This release

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page