Skip to main content

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.0

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.0
File Size Uploaded
ndx-0.6.0.tar.gz 24.3 kB Details

Built distribution (wheel)

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

Total release size: 48.3 kB

Release files / ndx-0.6.0.tar.gz

Download URL ndx-0.6.0.tar.gz
Size 24.3 kB
Tags Source
SHA-256 checksum
How to use checksums
fe276487c0dd4c10a598a03d776c5a8e68b6b7b5dae83bf1ad640da83c7f4699
BLAKE2b-256 checksum
How to use checksums
02aae8be3e88ceeda3ebfb3d914ccabb935d4966e9a3842374af8749c9473f59
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","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.0-py3-none-any.whl

Download URL ndx-0.6.0-py3-none-any.whl
Size 23.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b004145b2e2ce249b104e848a146227beb14d6501a5f5df19e3d941675994eca
BLAKE2b-256 checksum
How to use checksums
7dc7536306667b161eac6ddf1cfa18eb3a1fc4d44fab5ab09bedd4bf4f781618
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","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.0 This release

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