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)
| File | Size | Uploaded | |
|---|---|---|---|
| ndx-0.6.0.tar.gz | 24.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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}
|