A utility for generating a visually structured directory tree.
Project description
file_tree_display
A utility for generating a visually structured directory tree.
Modules
file_tree_display.py
This core module supports recursive traversal, customizable hierarchy styles, and inclusion / exclusion
patterns for directories and files.
Output can be displayed in the console or saved to a file.
Key Features
- Recursively displays and logs directory trees
- Efficient directory traversal
- Blazing fast (see Benchmarks below)
- Generates human-readable file tree structure
- Supports including / ignoring specific directories or files via pattern matching
- Customizable tree display output
- Optionally saves the resulting tree to a text file
- Lightweight, flexible and easily configurable
Benchmarks
The measurements were carried out on unfiltered folders containing multiple files und subdirectories, using SSD.
Avg. time was measured over 20 runs per configuration, using timeit decorator I've implemented in this package.
Comparing FileTreeDisplay (FTD) with
win_tree_wrapper
(Windows tree
wrapper which I've implemented for this purpose).
Benchtest code
Performance Comparison — FTD vs.tree
| Test Context | Results | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
*Without sorting FTD takes 162 ms and 2.338 s for Test1 and Test2, respectively.
FTD is roughly 1.7x–2.4x faster than the native tree binary across both datasets.
Brief Analysis
I. Linear scaling as a function of entries
FTD performance scales almost perfectly linearly with total entries:
- T1: 10 k files → 0.2 s
- T2: 138 k files → 2.9 s → ~14x more files → ~15x more runtime => expected by linearity.
II. Figuring out why tree is nearly 2 times slower than my FTD
Although tree is implemented in C, it incurs more I/O work:
- Performs full
lstat()on each entry (permissions, timestamps, etc.). - Prints incrementally to
stdout→ many system calls (syscalls). - Handles color / formatting output.
My FTD avoids this by:
- Using
os.scandir()(caching stat info). - Filtering and sorting in-memory.
- Buffering output before optional print/write.
Result: lower syscall count and fewer I/O stalls.
III. Python overhead is clearly negligible
Even at 2.9 s for ~160K entries, throughput ~55K entries/s — close to filesystem limits on SSDs. Measured wrapper overhead (~30 ms) is < 1 % of total runtime.
Key Insights
| Observation | Explanation |
|---|---|
FTD ~2x faster than tree |
Avoids per-file printing and redundant stats. |
| I/O-bound execution | Filesystem metadata fetch dominates total time. |
| Linear runtime scaling | Recursive generator design adds no hidden overhead. |
| Stable memory footprint | Uses streaming generators and StringIO buffering. |
Conclusions
- FTD outperforms
treeby roughly 2x on both moderate and large datasets. - Runtime scales linearly with total directory entries.
- Python layer overhead is negligible — performance is bounded by kernel I/O.
Class Overview
FileTreeDisplay
Constructs and manages the visual representation of a folder structure of a path or of a disk drive.
Initialization Parameters
| Parameter | Type | Description |
|---|---|---|
root_dir |
str |
Path to the directory to scan. |
filepath |
str / None |
Optional output destination for the saved file tree. |
ignore_dirs |
list[str] or set[str] or None |
Directory names or patterns to skip. |
ignore_files |
list[str] or set[str] or None |
File names or patterns to skip. |
include_dirs |
list[str] or set[str] or None |
Only include specified folder names or patterns. |
include_files |
list[str] or set[str] or None |
Only include specified file names or patterns, '*.pdf' - only include pdfs. |
style |
str |
Characters used to mark hierarchy levels. Defaults to 'classic'. |
indent |
int |
Number of style characters per level. Defaults 2. |
files_first |
bool |
Determines whether to list files first. Defaults to False. |
skip_sorting |
bool |
Skip sorting directly, even if configured. |
sort_key_name |
str |
Sort key. Lexicographic ('lex') or 'custom'. Defaults to 'natural'. |
reverse |
bool |
Reversed sorting order. |
custom_sort |
Callable[[str], Any] / None |
Custom sort key function. |
title |
str |
Custom title shown in the output. |
save2file |
bool |
Save file tree (folder structure) info into a file. |
printout |
bool |
Print file tree info. |
Core Methods
-
file_tree_display(save2file: bool = True) -> str | None
Generates the directory tree. Ifsave2file=True, saves the output; otherwise prints it directly. -
_build_tree(dir_path, *, prefix, style, sort_key, files_first, dir_filter, file_filter, reverse, indent) -> Generator[str, None, None]
Recursively traverses the directory tree in depth-first order (DFS) and yields formatted lines representing the file and folder structure.
| Parameter | Type | Description |
|---|---|---|
dir_path |
str |
Path to the directory being traversed. |
prefix |
str |
Current indentation prefix for nested entries. |
style |
dict[str, str] |
Connector style mapping with keys: branch, end, space, and vertical. |
sort_key |
Callable[[str], Any] |
Function used to sort directory and file names. |
files_first |
bool |
If True, list files before subdirectories. |
dir_filter, file_filter |
Callable[[str], bool] |
Predicates to include or exclude directories and files. |
reverse |
bool |
If True, reverses the sort order. |
indent |
int |
Number of spaces (or repeated characters) per indentation level. |
Example Usage
from pathlib import Path
from nano_dev_utils.file_tree_display import FileTreeDisplay
root = r'c:/your_root_dir'
target_path = r'c:/your_target_path'
filename = 'filetree.md'
filepath = str(Path(target_path, filename))
ftd = FileTreeDisplay(root_dir=root,
ignore_dirs=['.git', 'node_modules', '.idea'],
ignore_files=['.gitignore', '*.toml'],
style='classic',
include_dirs=['src', 'tests', 'snapshots'],
filepath=filepath,
sort_key_name='custom',
custom_sort=(lambda x: any(ext in x.lower() for ext in ('jpg', 'png'))),
files_first=True,
reverse=True
)
ftd.file_tree_display()
Custom connector style
You can define and register your own connector styles at runtime by adding entries to style_dict:
from nano_dev_utils.file_tree_display import FileTreeDisplay
ftd = FileTreeDisplay(root_dir=".")
ftd.style_dict["plus2"] = ftd.connector_styler("+-- ", "+== ")
ftd.style = "plus2"
ftd.printout = True
ftd.file_tree_display()
FTD CLI — File Tree Display
The FTD CLI (ftd) is a lightweight, configurable command-line tool for displaying or exporting a formatted file tree of a given directory.
It’s designed for flexibility, allowing users to control inclusion/exclusion rules, visual style, sorting behavior, and output options.
Features
- Generate a clean, formatted file tree of any directory
- Choose from multiple connector styles (
classic,dash,arrow,plus) - Fine-grained control over included/excluded files and directories
- Flexible sorting modes (
natural,lex, orcustom) - Optionally export the tree to a file or print directly to stdout
- Supports configuration via JSON config file
Usage
ftd [OPTIONS]
Example:
ftd --root-dir ./src --style arrow --files-first --printout
This displays the tree structure of the src directory using the arrow connector style, listing files before directories, and prints the output to the console.
Command-Line Options
| Option | Alias | Type | Description | Default |
|---|---|---|---|---|
--cfg |
– | str |
Path to a JSON configuration file. | – |
--root-dir |
-r |
str |
Root directory to display. | – |
--filepath |
-o |
str |
Output file path for exported tree. | – |
--ignore-dirs |
– | str… |
Directories to exclude from the tree. | – |
--ignore-files |
– | str… |
Files to exclude from the tree. | – |
--include-dirs |
– | str… |
Directories to explicitly include. | – |
--include-files |
– | str… |
Files to explicitly include. | – |
--style |
-s |
str |
Tree connector style (classic, dash, arrow, plus). |
classic |
--indent |
-i |
int |
Indent width (spaces) per directory level. | 2 |
--files-first |
-f |
flag | List files before directories. | False |
--skip-sorting |
– | flag | Disable sorting altogether. | False |
--sort-key |
– | str |
Sorting key: natural, lex, or custom. |
natural |
--reverse |
– | flag | Reverse the sort order. | False |
--no-save |
– | flag | Do not save output to file (useful with --printout). |
False |
--printout |
-p |
flag | Print the generated tree to stdout. | False |
--version |
-v |
flag | Show the current version of FTD and exit. | – |
Configuration via JSON file
FTD can also load parameters from a JSON config file:
{
"root_dir": "./project",
"ignore_dirs": ["__pycache__", "build"],
"ignore_files": [".DS_Store"],
"style": "dash",
"files_first": true,
"printout": true
}
Run it using:
ftd --cfg path/to/config.json
Command-line arguments always override config file values.
Examples
Display the current directory with default settings:
ftd -r .
Display a tree with dashed connectors, ignoring test folders, and print it:
ftd -r ./src --ignore-dirs tests --style dash --printout
Export a formatted tree to a file:
ftd -r ./app --filepath tree.txt
Reverse lexical sort with 4-space indentation:
ftd -r ./data --sort-key lex --reverse --indent 4
🧾 Output Example
src
├── main.py
├── utils
│ ├── helpers.py
│ └── validators.py
└── tests
├── test_main.py
└── test_utils.py
License
This project is licensed under the MIT License. See LICENSE for details.
Project details
Release history Release notifications | RSS feed
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 file_tree_display-1.1.0.tar.gz.
File metadata
- Download URL: file_tree_display-1.1.0.tar.gz
- Upload date:
- Size: 29.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.10.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa2d8407df076ccbf12467dae6e5dc11e04934cd8d8ff16808489cd13a12519f
|
|
| MD5 |
1063967f520edfb68689c5ebbf334b69
|
|
| BLAKE2b-256 |
bd185b122b025525ad6244d685ae397c6a97890f089cac6fcb4742a193626a59
|
File details
Details for the file file_tree_display-1.1.0-py3-none-any.whl.
File metadata
- Download URL: file_tree_display-1.1.0-py3-none-any.whl
- Upload date:
- Size: 13.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.10.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
030b3bb12bf919b0ede01043e02fda7ca247f74f33eae80bff9715788937bdcd
|
|
| MD5 |
e931a310d14ceb8317a7db2f58e124e1
|
|
| BLAKE2b-256 |
abc8ecd3fc33feadab91a8209c83820c21c65b25835ad92dac9371730a8e6026
|