python-dirtt — Directory Tree Templater
Dirtt generates directory and file structures from simple XML or JSON templates that describe repeatedly used filesystem layouts — project scaffolds, VFX show structures, or any tree you build more than once.
Write the layout once as a template, then stamp it out anywhere with variables filled in:
$ dirtt create -t project.xml --var project_root=/jobs --var project_path=commercial_spot
created tree: 81 actions
- Zero runtime dependencies — pure Python standard library
- Python 3.10+
- Templates in XML (the classic dirtt dialect, unchanged since 0.x) or JSON
--dry-runprints the full plan without touching the filesystem- Introspection: point dirtt at an existing tree and get a template back
(c) 2011–2026 Robert Moggach and contributors. Licensed under the MIT license.
Install
pip install python-dirtt
Command line
dirtt create -t TEMPLATE [--var KEY=VALUE ...] [--dest DIR] [--dry-run] [-i] [-w] [-v]
dirtt list # show the packaged example templates
dirtt placeholders -t TEMPLATE # show the variables a template requires
dirtt introspect PATH [-o FILE]# generate a template from a real tree
create prompts interactively for any {{placeholder}} you don't pass
with --var. --dry-run prints each planned action (mkdir, write,
symlink) instead of performing it. -i/--interactive confirms each
directory; answering no skips that directory and everything inside it.
-w/--warn fails instead of continuing when a directory already exists.
Library
from dirtt import build
# create the tree
build("project.xml", {"project_root": "/jobs", "project_path": "myproject"})
# or preview first
for action in build("project.xml", context, dry_run=True):
print(action.describe())
The stages are also available separately:
from dirtt import load_template, plan, execute, introspect
tree = load_template("project.xml", context) # frozen dataclass Tree
actions = plan(tree, dest="/somewhere/else") # ordered list[Action], absolute paths
execute(actions) # apply (or dry_run=True)
xml = introspect("/jobs/existing_project") # tree -> template
Errors raise dirtt.DirttError subclasses (TemplateError,
BuildError); the library never prints or exits.
XML templates
The dialect is unchanged from dirtt 0.x:
<?xml version="1.0" encoding="UTF-8"?>
<dirtt name="Project Tree" version="1.0"
dirname="{{project_root}}" basename="{{project_path}}"
username="pipeline" group="artist" perms="02755"
xmlns:xi="http://www.w3.org/2001/XInclude">
<dir basename="src" perms="02755">
<file basename="README.md" href="readme_snippet.md" perms="0644"/>
</dir>
<dir basename="renders" id="renders-dir"/>
<link basename="latest" idref="renders-dir"/>
<xi:include href="shared_structure.xml"/>
</dirtt>
dirtt— the root directory:dirname(parent path) +basename(directory name). Ifbasenameis omitted it is split offdirname.dir— a directory; nestsdir,file, andlinkelements.file— a file;hrefnames a content template (resolved next to the tree template, then in the packaged templates) rendered with the same{{variables}}; withouthrefthe file is created empty.link— a symlink;refis a literal target path,idrefpoints at theidof adirin the same tree. Links are created last.xi:include— splice another template's children in place;hrefmay be relative, absolute, or anhttp(s)://URL.permsis octal text ("02775");username/groupare applied withchownonly when running as root, and skipped otherwise.
JSON templates
The same schema as JSON — children are tagged with "type":
{
"name": "Project Tree",
"dirname": "{{project_root}}",
"basename": "{{project_path}}",
"perms": "02755",
"children": [
{ "type": "dir", "basename": "src", "children": [
{ "type": "file", "basename": "notes.txt", "content": "for {{project_path}}" }
]},
{ "type": "dir", "basename": "renders", "id": "renders-dir" },
{ "type": "link", "basename": "latest", "idref": "renders-dir" },
{ "include": "shared_structure.json" }
]
}
Files may carry inline "content" (JSON only) or an "href" like XML.
Migrating from 0.2.x
| 0.2.x | 1.0 |
|---|---|
mktree.py --template ... --interactive |
dirtt create -t ... -i |
mktemplate.py -p PATH |
dirtt introspect PATH |
mkproject.py |
dirtt create with your studio's template |
DirectoryTreeHandler(verbose, template, kwargs).run() |
build(template, kwargs) |
dirtt.util.template (Paste engine, eval-based) |
{{name}} placeholders only |
| Python 2, distutils | Python 3.10+, pyproject.toml |
Your existing XML templates work as-is. The old template engine's
{{if}}/{{for}}/{{py:}} constructs were never used by tree
templates and are no longer supported.
Development
git clone https://github.com/rjmoggach/python-dirtt
cd python-dirtt
uv run --group dev pytest
Contributions welcome — code, tests, docs, bug reports, ideas.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file python_dirtt-1.0.1.tar.gz.
File metadata
- Download URL: python_dirtt-1.0.1.tar.gz
- Upload date:
- Size: 24.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7667f9f5132c68916203c4f6cbccf490b307d58ee4d4fefc643f66f5a53a8186
|
|
| MD5 |
47b398f6f1bceaa1f45da7e57414a8e4
|
|
| BLAKE2b-256 |
6acadb716e0658d95345a852d8a55199d0c7c36a75d6affe0b9128a8ead354fe
|
File details
Details for the file python_dirtt-1.0.1-py3-none-any.whl.
File metadata
- Download URL: python_dirtt-1.0.1-py3-none-any.whl
- Upload date:
- Size: 25.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f2fedfb3a3d6a8404315a24a10967dd47d6953821f61e013156555a3d602d7d0
|
|
| MD5 |
55f6602654f3e9b9b13e1dedd9a4f84d
|
|
| BLAKE2b-256 |
9d3b0be1b284e95cc0cfafa289e31990a41fe6c2e8ac9d46d109c552e6317439
|