treex-cli 0.1.0__tar.gz → 0.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {treex_cli-0.1.0/treex_cli.egg-info → treex_cli-0.1.2}/PKG-INFO +55 -15
- treex_cli-0.1.2/README.md +100 -0
- {treex_cli-0.1.0 → treex_cli-0.1.2}/pyproject.toml +3 -3
- {treex_cli-0.1.0 → treex_cli-0.1.2}/treex.py +98 -81
- {treex_cli-0.1.0 → treex_cli-0.1.2/treex_cli.egg-info}/PKG-INFO +55 -15
- treex_cli-0.1.0/README.md +0 -60
- {treex_cli-0.1.0 → treex_cli-0.1.2}/LICENSE +0 -0
- {treex_cli-0.1.0 → treex_cli-0.1.2}/setup.cfg +0 -0
- {treex_cli-0.1.0 → treex_cli-0.1.2}/treex_cli.egg-info/SOURCES.txt +0 -0
- {treex_cli-0.1.0 → treex_cli-0.1.2}/treex_cli.egg-info/dependency_links.txt +0 -0
- {treex_cli-0.1.0 → treex_cli-0.1.2}/treex_cli.egg-info/entry_points.txt +0 -0
- {treex_cli-0.1.0 → treex_cli-0.1.2}/treex_cli.egg-info/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: treex-cli
|
|
3
|
-
Version: 0.1.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: List directory contents as a tree with file metadata
|
|
5
5
|
Author: Corey Goldberg
|
|
6
6
|
Maintainer: Corey Goldberg
|
|
7
7
|
License-Expression: MIT
|
|
@@ -25,7 +25,7 @@ Dynamic: license-file
|
|
|
25
25
|
|
|
26
26
|
# treex
|
|
27
27
|
|
|
28
|
-
##
|
|
28
|
+
## List directory contents as a tree with file metadata
|
|
29
29
|
|
|
30
30
|
- Copyright (c) 2026 [Corey Goldberg][github-profile]
|
|
31
31
|
- Development: [GitHub][github-repo]
|
|
@@ -36,14 +36,49 @@ Dynamic: license-file
|
|
|
36
36
|
|
|
37
37
|
## About
|
|
38
38
|
|
|
39
|
-
`treex` is a command-line utility
|
|
40
|
-
|
|
41
|
-
characters. File names include their human-readable size and, optionally,
|
|
42
|
-
modification time. Text files also include their line count, while binary and
|
|
43
|
-
unreadable files are marked with their type. When Git is installed, it respects
|
|
44
|
-
`.gitignore` rules.
|
|
39
|
+
`treex` is a command-line utility that recursively scans a directory and
|
|
40
|
+
displays its contents as a tree along with file metadata.
|
|
45
41
|
|
|
46
|
-
|
|
42
|
+
- File names show human-readable sizes
|
|
43
|
+
- Text files show line counts
|
|
44
|
+
- Binary and unreadable files show their type
|
|
45
|
+
- Modification timestamps are optional
|
|
46
|
+
- Respects `.gitignore` rules when Git is installed
|
|
47
|
+
|
|
48
|
+
----
|
|
49
|
+
|
|
50
|
+
## Status
|
|
51
|
+
|
|
52
|
+
<table>
|
|
53
|
+
<tr>
|
|
54
|
+
<td>Latest Version</td>
|
|
55
|
+
<td>
|
|
56
|
+
<a href="https://pypi.org/project/treex-cli">
|
|
57
|
+
<img src="https://img.shields.io/pypi/v/treex-cli.svg">
|
|
58
|
+
</a>
|
|
59
|
+
</td>
|
|
60
|
+
</tr>
|
|
61
|
+
<tr>
|
|
62
|
+
<td>Tests (CI)</td>
|
|
63
|
+
<td>
|
|
64
|
+
<a href="https://github.com/cgoldberg/treex/actions/workflows/test.yml">
|
|
65
|
+
<img src="https://github.com/cgoldberg/treex/actions/workflows/test.yml/badge.svg">
|
|
66
|
+
</a>
|
|
67
|
+
</td>
|
|
68
|
+
</tr>
|
|
69
|
+
<tr>
|
|
70
|
+
<td>Supported Python Versions</td>
|
|
71
|
+
<td>
|
|
72
|
+
<a href="https://pypi.org/project/treex-cli">
|
|
73
|
+
<img src="https://img.shields.io/pypi/pyversions/treex-cli">
|
|
74
|
+
</a>
|
|
75
|
+
</td>
|
|
76
|
+
</tr>
|
|
77
|
+
</table>
|
|
78
|
+
|
|
79
|
+
----
|
|
80
|
+
|
|
81
|
+
## Requirements
|
|
47
82
|
|
|
48
83
|
- Python 3.10+
|
|
49
84
|
- Git 2.0+ (optional)
|
|
@@ -64,22 +99,27 @@ Install `treex` from [PyPI][pypi-home] using either `pip` or `pipx`:
|
|
|
64
99
|
|
|
65
100
|
```
|
|
66
101
|
$ treex --help
|
|
67
|
-
usage: treex [-h] [-a] [-
|
|
102
|
+
usage: treex [-h] [-a] [-m] [-s] [directory]
|
|
68
103
|
|
|
69
|
-
|
|
104
|
+
List directory contents as a tree with file metadata.
|
|
70
105
|
|
|
71
106
|
positional arguments:
|
|
72
107
|
directory directory to scan (default: current directory)
|
|
73
108
|
|
|
74
109
|
options:
|
|
75
110
|
-h, --help show this help message and exit
|
|
76
|
-
-a, --all show all files
|
|
77
|
-
-w, --width N starting column for file metadata (default: 50)
|
|
111
|
+
-a, --all show all files (including those ignored by Git)
|
|
78
112
|
-m, --modified show file modification times
|
|
113
|
+
-s, --summary show summary only
|
|
79
114
|
```
|
|
80
115
|
|
|
116
|
+
----
|
|
117
|
+
|
|
118
|
+
## Screenshot
|
|
119
|
+
|
|
120
|
+

|
|
121
|
+
|
|
81
122
|
[github-profile]: https://github.com/cgoldberg
|
|
82
123
|
[github-repo]: https://github.com/cgoldberg/treex
|
|
83
124
|
[pypi-home]: https://pypi.org/project/treex-cli
|
|
84
125
|
[mit-license]: https://raw.githubusercontent.com/cgoldberg/treex/refs/heads/main/LICENSE
|
|
85
|
-
[tree-home]: https://oldmanprogrammer.net/source.php?dir=projects/tree
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# treex
|
|
2
|
+
|
|
3
|
+
## List directory contents as a tree with file metadata
|
|
4
|
+
|
|
5
|
+
- Copyright (c) 2026 [Corey Goldberg][github-profile]
|
|
6
|
+
- Development: [GitHub][github-repo]
|
|
7
|
+
- Releases: [PyPI][pypi-home]
|
|
8
|
+
- License: [MIT][mit-license]
|
|
9
|
+
|
|
10
|
+
----
|
|
11
|
+
|
|
12
|
+
## About
|
|
13
|
+
|
|
14
|
+
`treex` is a command-line utility that recursively scans a directory and
|
|
15
|
+
displays its contents as a tree along with file metadata.
|
|
16
|
+
|
|
17
|
+
- File names show human-readable sizes
|
|
18
|
+
- Text files show line counts
|
|
19
|
+
- Binary and unreadable files show their type
|
|
20
|
+
- Modification timestamps are optional
|
|
21
|
+
- Respects `.gitignore` rules when Git is installed
|
|
22
|
+
|
|
23
|
+
----
|
|
24
|
+
|
|
25
|
+
## Status
|
|
26
|
+
|
|
27
|
+
<table>
|
|
28
|
+
<tr>
|
|
29
|
+
<td>Latest Version</td>
|
|
30
|
+
<td>
|
|
31
|
+
<a href="https://pypi.org/project/treex-cli">
|
|
32
|
+
<img src="https://img.shields.io/pypi/v/treex-cli.svg">
|
|
33
|
+
</a>
|
|
34
|
+
</td>
|
|
35
|
+
</tr>
|
|
36
|
+
<tr>
|
|
37
|
+
<td>Tests (CI)</td>
|
|
38
|
+
<td>
|
|
39
|
+
<a href="https://github.com/cgoldberg/treex/actions/workflows/test.yml">
|
|
40
|
+
<img src="https://github.com/cgoldberg/treex/actions/workflows/test.yml/badge.svg">
|
|
41
|
+
</a>
|
|
42
|
+
</td>
|
|
43
|
+
</tr>
|
|
44
|
+
<tr>
|
|
45
|
+
<td>Supported Python Versions</td>
|
|
46
|
+
<td>
|
|
47
|
+
<a href="https://pypi.org/project/treex-cli">
|
|
48
|
+
<img src="https://img.shields.io/pypi/pyversions/treex-cli">
|
|
49
|
+
</a>
|
|
50
|
+
</td>
|
|
51
|
+
</tr>
|
|
52
|
+
</table>
|
|
53
|
+
|
|
54
|
+
----
|
|
55
|
+
|
|
56
|
+
## Requirements
|
|
57
|
+
|
|
58
|
+
- Python 3.10+
|
|
59
|
+
- Git 2.0+ (optional)
|
|
60
|
+
- UTF-8-compatible terminal
|
|
61
|
+
|
|
62
|
+
----
|
|
63
|
+
|
|
64
|
+
## Installation
|
|
65
|
+
|
|
66
|
+
Install `treex` from [PyPI][pypi-home] using either `pip` or `pipx`:
|
|
67
|
+
|
|
68
|
+
- `pip install treex-cli`
|
|
69
|
+
- `pipx install treex-cli`
|
|
70
|
+
|
|
71
|
+
----
|
|
72
|
+
|
|
73
|
+
## Usage
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
$ treex --help
|
|
77
|
+
usage: treex [-h] [-a] [-m] [-s] [directory]
|
|
78
|
+
|
|
79
|
+
List directory contents as a tree with file metadata.
|
|
80
|
+
|
|
81
|
+
positional arguments:
|
|
82
|
+
directory directory to scan (default: current directory)
|
|
83
|
+
|
|
84
|
+
options:
|
|
85
|
+
-h, --help show this help message and exit
|
|
86
|
+
-a, --all show all files (including those ignored by Git)
|
|
87
|
+
-m, --modified show file modification times
|
|
88
|
+
-s, --summary show summary only
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
----
|
|
92
|
+
|
|
93
|
+
## Screenshot
|
|
94
|
+
|
|
95
|
+

|
|
96
|
+
|
|
97
|
+
[github-profile]: https://github.com/cgoldberg
|
|
98
|
+
[github-repo]: https://github.com/cgoldberg/treex
|
|
99
|
+
[pypi-home]: https://pypi.org/project/treex-cli
|
|
100
|
+
[mit-license]: https://raw.githubusercontent.com/cgoldberg/treex/refs/heads/main/LICENSE
|
|
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "treex-cli"
|
|
7
|
-
version = "0.1.
|
|
8
|
-
description
|
|
7
|
+
version = "0.1.2"
|
|
8
|
+
description="List directory contents as a tree with file metadata"
|
|
9
9
|
license = "MIT"
|
|
10
10
|
license-files = ["LICENSE"]
|
|
11
11
|
authors = [{name = "Corey Goldberg"}]
|
|
@@ -68,7 +68,7 @@ ignore = [
|
|
|
68
68
|
fixable = ["ALL"]
|
|
69
69
|
|
|
70
70
|
[tool.ruff.lint.per-file-ignores]
|
|
71
|
-
"**/test_*.py" = ["S101", "S108"]
|
|
71
|
+
"**/test_*.py" = ["S101", "S108", "SLF001"]
|
|
72
72
|
|
|
73
73
|
[tool.ruff.format]
|
|
74
74
|
docstring-code-format = true
|
|
@@ -2,21 +2,14 @@
|
|
|
2
2
|
# SPDX-License-Identifier: MIT
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
"""
|
|
5
|
+
"""List directory contents as a tree with file metadata.
|
|
6
6
|
|
|
7
|
-
The directory tree is rendered using Unicode box-drawing characters.
|
|
8
|
-
displayed with their human-readable size and, optionally, modification time. Text
|
|
9
|
-
files also include their line count. Binary and unreadable files are marked with
|
|
10
|
-
their type.
|
|
7
|
+
The directory tree is rendered using Unicode box-drawing characters.
|
|
11
8
|
|
|
12
9
|
When run inside a Git repository, files and directories ignored by Git
|
|
13
10
|
are automatically excluded using Git's own ignore rules. If Git is not
|
|
14
11
|
installed, or the directory is not part of a Git repository, the
|
|
15
12
|
filesystem is scanned normally without Git filtering.
|
|
16
|
-
|
|
17
|
-
Use --all to disable Git ignore filtering and show all files.
|
|
18
|
-
Use --width to control the column at which file metadata starts.
|
|
19
|
-
Use --modified to show file modification times.
|
|
20
13
|
"""
|
|
21
14
|
|
|
22
15
|
import argparse
|
|
@@ -25,17 +18,15 @@ from contextlib import suppress
|
|
|
25
18
|
from datetime import datetime
|
|
26
19
|
from pathlib import Path
|
|
27
20
|
|
|
28
|
-
DEFAULT_METADATA_COLUMN = 50
|
|
29
|
-
|
|
30
21
|
|
|
31
22
|
class GitIgnore:
|
|
32
|
-
"""Use Git's
|
|
23
|
+
"""Use Git's ignore rules when available."""
|
|
33
24
|
|
|
34
25
|
def __init__(self, directory):
|
|
35
26
|
self.directory = Path(directory).resolve()
|
|
36
27
|
self.enabled = False
|
|
37
28
|
self.repo_root = None
|
|
38
|
-
# Git
|
|
29
|
+
# Check Git availability and find the repository root
|
|
39
30
|
with suppress(OSError):
|
|
40
31
|
result = subprocess.run(
|
|
41
32
|
["git", "rev-parse", "--show-toplevel"],
|
|
@@ -45,12 +36,13 @@ class GitIgnore:
|
|
|
45
36
|
text=True,
|
|
46
37
|
check=False,
|
|
47
38
|
)
|
|
39
|
+
# Enable Git support if this is a repository
|
|
48
40
|
if result.returncode == 0:
|
|
49
41
|
self.repo_root = Path(result.stdout.strip()).resolve()
|
|
50
42
|
self.enabled = True
|
|
51
43
|
|
|
52
44
|
def ignored(self, path):
|
|
53
|
-
"""
|
|
45
|
+
"""Check if Git considers the path ignored."""
|
|
54
46
|
if not self.enabled:
|
|
55
47
|
return False
|
|
56
48
|
try:
|
|
@@ -80,12 +72,12 @@ def format_size(size): # noqa: RET503
|
|
|
80
72
|
|
|
81
73
|
|
|
82
74
|
def format_modified(timestamp):
|
|
83
|
-
"""Format a modification timestamp
|
|
75
|
+
"""Format a modification timestamp."""
|
|
84
76
|
return datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M")
|
|
85
77
|
|
|
86
78
|
|
|
87
79
|
def is_binary_file(path, chunk_size=8192):
|
|
88
|
-
"""
|
|
80
|
+
"""Check if the file appears to be binary."""
|
|
89
81
|
try:
|
|
90
82
|
with path.open("rb") as f:
|
|
91
83
|
chunk = f.read(chunk_size)
|
|
@@ -107,18 +99,15 @@ def is_binary_file(path, chunk_size=8192):
|
|
|
107
99
|
|
|
108
100
|
def count_lines(path):
|
|
109
101
|
"""Count lines without loading the entire file into memory."""
|
|
110
|
-
count = 0
|
|
111
102
|
try:
|
|
112
103
|
with path.open("rb") as f:
|
|
113
|
-
for _ in f
|
|
114
|
-
count += 1
|
|
104
|
+
return sum(1 for _ in f)
|
|
115
105
|
except OSError:
|
|
116
106
|
return None
|
|
117
|
-
return count
|
|
118
107
|
|
|
119
108
|
|
|
120
109
|
def file_info(path):
|
|
121
|
-
"""
|
|
110
|
+
"""Get file info."""
|
|
122
111
|
try:
|
|
123
112
|
stat = path.stat()
|
|
124
113
|
size = stat.st_size
|
|
@@ -134,61 +123,89 @@ def file_info(path):
|
|
|
134
123
|
return size_text, f"{lines:,} lines", size, modified
|
|
135
124
|
|
|
136
125
|
|
|
137
|
-
def
|
|
138
|
-
|
|
139
|
-
prefix="",
|
|
140
|
-
stats=None,
|
|
141
|
-
gitignore=None,
|
|
142
|
-
width=DEFAULT_METADATA_COLUMN,
|
|
143
|
-
show_modified=False,
|
|
144
|
-
):
|
|
145
|
-
"""Recursively print the directory tree."""
|
|
146
|
-
if stats is None:
|
|
147
|
-
stats = {
|
|
148
|
-
"directories": 0,
|
|
149
|
-
"files": 0,
|
|
150
|
-
"total_size": 0,
|
|
151
|
-
}
|
|
152
|
-
path = Path(directory)
|
|
126
|
+
def _get_tree_entries(path, gitignore):
|
|
127
|
+
"""Get entries to include in the tree."""
|
|
153
128
|
try:
|
|
154
129
|
entries = list(path.iterdir())
|
|
155
130
|
except PermissionError:
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
131
|
+
return None
|
|
132
|
+
# Filter ignored entries and Git's internal directory
|
|
133
|
+
entries = [
|
|
134
|
+
entry
|
|
135
|
+
for entry in entries
|
|
136
|
+
if not entry.is_symlink()
|
|
137
|
+
and (not gitignore or (entry.name != ".git" and not gitignore.ignored(entry)))
|
|
138
|
+
]
|
|
139
|
+
# Group directories first and sort names case-insensitive
|
|
140
|
+
entries.sort(key=lambda p: (p.is_file(), p.name.casefold()))
|
|
141
|
+
return entries
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _collect_tree(
|
|
145
|
+
path,
|
|
146
|
+
prefix,
|
|
147
|
+
stats,
|
|
148
|
+
gitignore,
|
|
149
|
+
rows,
|
|
150
|
+
show_modified,
|
|
151
|
+
):
|
|
152
|
+
"""Walk the tree once and collect the output rows."""
|
|
153
|
+
entries = _get_tree_entries(path, gitignore)
|
|
154
|
+
if entries is None:
|
|
155
|
+
rows.append((prefix + "└── [permission denied]", None))
|
|
156
|
+
return
|
|
157
|
+
for index, entry in enumerate(entries):
|
|
158
|
+
is_last = index == len(entries) - 1
|
|
170
159
|
connector = "└── " if is_last else "├── "
|
|
160
|
+
tree_name = prefix + connector + entry.name
|
|
171
161
|
if entry.is_dir():
|
|
172
162
|
stats["directories"] += 1
|
|
173
|
-
|
|
163
|
+
rows.append((tree_name, None))
|
|
164
|
+
# Indent nested entries, preserving the tree's vertical branch
|
|
174
165
|
extension = " " if is_last else "│ "
|
|
175
|
-
|
|
166
|
+
_collect_tree(
|
|
176
167
|
entry,
|
|
177
168
|
prefix + extension,
|
|
178
169
|
stats,
|
|
179
170
|
gitignore,
|
|
180
|
-
|
|
171
|
+
rows,
|
|
181
172
|
show_modified,
|
|
182
173
|
)
|
|
183
174
|
elif entry.is_file():
|
|
184
175
|
stats["files"] += 1
|
|
185
|
-
|
|
186
|
-
stats["total_size"] +=
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
176
|
+
size_text, info, size, modified = file_info(entry)
|
|
177
|
+
stats["total_size"] += size
|
|
178
|
+
timestamp = modified if show_modified else None
|
|
179
|
+
rows.append((tree_name, (size_text, info, timestamp)))
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def print_tree(
|
|
183
|
+
directory,
|
|
184
|
+
prefix="",
|
|
185
|
+
stats=None,
|
|
186
|
+
gitignore=None,
|
|
187
|
+
show_modified=False,
|
|
188
|
+
show_tree=True,
|
|
189
|
+
):
|
|
190
|
+
"""Print the directory tree with aligned file metadata."""
|
|
191
|
+
if stats is None:
|
|
192
|
+
stats = {"directories": 0, "files": 0, "total_size": 0}
|
|
193
|
+
rows = []
|
|
194
|
+
# Walk the filesystem once and collect the output
|
|
195
|
+
_collect_tree(Path(directory), prefix, stats, gitignore, rows, show_modified)
|
|
196
|
+
if show_tree:
|
|
197
|
+
# Align file metadata with the longest tree/name
|
|
198
|
+
max_tree_name_width = max(
|
|
199
|
+
(len(tree_name) for tree_name, _ in rows),
|
|
200
|
+
default=0,
|
|
201
|
+
)
|
|
202
|
+
for tree_name, file_info_data in rows:
|
|
203
|
+
if file_info_data is None:
|
|
204
|
+
print(tree_name)
|
|
205
|
+
continue
|
|
206
|
+
size_text, info, modified = file_info_data
|
|
207
|
+
output = f"{tree_name:<{max_tree_name_width}}{size_text:>10} {info:<10}"
|
|
208
|
+
if modified is not None:
|
|
192
209
|
output += f" {modified}"
|
|
193
210
|
print(output)
|
|
194
211
|
return stats
|
|
@@ -197,7 +214,7 @@ def print_tree(
|
|
|
197
214
|
def parse_args(argv=None):
|
|
198
215
|
"""Parse command-line arguments."""
|
|
199
216
|
parser = argparse.ArgumentParser(
|
|
200
|
-
description="
|
|
217
|
+
description="List directory contents as a tree with file metadata.",
|
|
201
218
|
)
|
|
202
219
|
parser.add_argument(
|
|
203
220
|
"directory",
|
|
@@ -210,15 +227,7 @@ def parse_args(argv=None):
|
|
|
210
227
|
"-a",
|
|
211
228
|
"--all",
|
|
212
229
|
action="store_true",
|
|
213
|
-
help="show all files
|
|
214
|
-
)
|
|
215
|
-
parser.add_argument(
|
|
216
|
-
"-w",
|
|
217
|
-
"--width",
|
|
218
|
-
type=int,
|
|
219
|
-
default=DEFAULT_METADATA_COLUMN,
|
|
220
|
-
metavar="N",
|
|
221
|
-
help=f"starting column for file metadata (default: {DEFAULT_METADATA_COLUMN})",
|
|
230
|
+
help="show all files (including those ignored by Git)",
|
|
222
231
|
)
|
|
223
232
|
parser.add_argument(
|
|
224
233
|
"-m",
|
|
@@ -226,6 +235,12 @@ def parse_args(argv=None):
|
|
|
226
235
|
action="store_true",
|
|
227
236
|
help="show file modification times",
|
|
228
237
|
)
|
|
238
|
+
parser.add_argument(
|
|
239
|
+
"-s",
|
|
240
|
+
"--summary",
|
|
241
|
+
action="store_true",
|
|
242
|
+
help="show summary only",
|
|
243
|
+
)
|
|
229
244
|
return parser.parse_args(argv)
|
|
230
245
|
|
|
231
246
|
|
|
@@ -235,20 +250,22 @@ def main():
|
|
|
235
250
|
if not path.is_dir():
|
|
236
251
|
print(f"Not a directory: {path}")
|
|
237
252
|
return 1
|
|
238
|
-
if
|
|
239
|
-
print("Width must be greater than zero.")
|
|
240
|
-
return 1
|
|
241
|
-
# Only initialize Git integration when it will actually be used.
|
|
253
|
+
# Only initialize Git support if it will be used
|
|
242
254
|
gitignore = None if args.all else GitIgnore(path)
|
|
243
|
-
|
|
255
|
+
show_tree = not args.summary
|
|
256
|
+
if show_tree:
|
|
257
|
+
print(path)
|
|
244
258
|
stats = print_tree(
|
|
245
|
-
path,
|
|
259
|
+
path,
|
|
260
|
+
gitignore=gitignore,
|
|
261
|
+
show_modified=args.modified,
|
|
262
|
+
show_tree=show_tree,
|
|
246
263
|
)
|
|
264
|
+
if show_tree:
|
|
265
|
+
print()
|
|
247
266
|
print(
|
|
248
|
-
f""
|
|
249
|
-
f""
|
|
250
|
-
f"{stats['directories']} directories, "
|
|
251
|
-
f"{stats['files']} files, "
|
|
267
|
+
f"{stats['directories']} directories • "
|
|
268
|
+
f"{stats['files']} files • "
|
|
252
269
|
f"{format_size(stats['total_size'])}"
|
|
253
270
|
)
|
|
254
271
|
return 0
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: treex-cli
|
|
3
|
-
Version: 0.1.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: List directory contents as a tree with file metadata
|
|
5
5
|
Author: Corey Goldberg
|
|
6
6
|
Maintainer: Corey Goldberg
|
|
7
7
|
License-Expression: MIT
|
|
@@ -25,7 +25,7 @@ Dynamic: license-file
|
|
|
25
25
|
|
|
26
26
|
# treex
|
|
27
27
|
|
|
28
|
-
##
|
|
28
|
+
## List directory contents as a tree with file metadata
|
|
29
29
|
|
|
30
30
|
- Copyright (c) 2026 [Corey Goldberg][github-profile]
|
|
31
31
|
- Development: [GitHub][github-repo]
|
|
@@ -36,14 +36,49 @@ Dynamic: license-file
|
|
|
36
36
|
|
|
37
37
|
## About
|
|
38
38
|
|
|
39
|
-
`treex` is a command-line utility
|
|
40
|
-
|
|
41
|
-
characters. File names include their human-readable size and, optionally,
|
|
42
|
-
modification time. Text files also include their line count, while binary and
|
|
43
|
-
unreadable files are marked with their type. When Git is installed, it respects
|
|
44
|
-
`.gitignore` rules.
|
|
39
|
+
`treex` is a command-line utility that recursively scans a directory and
|
|
40
|
+
displays its contents as a tree along with file metadata.
|
|
45
41
|
|
|
46
|
-
|
|
42
|
+
- File names show human-readable sizes
|
|
43
|
+
- Text files show line counts
|
|
44
|
+
- Binary and unreadable files show their type
|
|
45
|
+
- Modification timestamps are optional
|
|
46
|
+
- Respects `.gitignore` rules when Git is installed
|
|
47
|
+
|
|
48
|
+
----
|
|
49
|
+
|
|
50
|
+
## Status
|
|
51
|
+
|
|
52
|
+
<table>
|
|
53
|
+
<tr>
|
|
54
|
+
<td>Latest Version</td>
|
|
55
|
+
<td>
|
|
56
|
+
<a href="https://pypi.org/project/treex-cli">
|
|
57
|
+
<img src="https://img.shields.io/pypi/v/treex-cli.svg">
|
|
58
|
+
</a>
|
|
59
|
+
</td>
|
|
60
|
+
</tr>
|
|
61
|
+
<tr>
|
|
62
|
+
<td>Tests (CI)</td>
|
|
63
|
+
<td>
|
|
64
|
+
<a href="https://github.com/cgoldberg/treex/actions/workflows/test.yml">
|
|
65
|
+
<img src="https://github.com/cgoldberg/treex/actions/workflows/test.yml/badge.svg">
|
|
66
|
+
</a>
|
|
67
|
+
</td>
|
|
68
|
+
</tr>
|
|
69
|
+
<tr>
|
|
70
|
+
<td>Supported Python Versions</td>
|
|
71
|
+
<td>
|
|
72
|
+
<a href="https://pypi.org/project/treex-cli">
|
|
73
|
+
<img src="https://img.shields.io/pypi/pyversions/treex-cli">
|
|
74
|
+
</a>
|
|
75
|
+
</td>
|
|
76
|
+
</tr>
|
|
77
|
+
</table>
|
|
78
|
+
|
|
79
|
+
----
|
|
80
|
+
|
|
81
|
+
## Requirements
|
|
47
82
|
|
|
48
83
|
- Python 3.10+
|
|
49
84
|
- Git 2.0+ (optional)
|
|
@@ -64,22 +99,27 @@ Install `treex` from [PyPI][pypi-home] using either `pip` or `pipx`:
|
|
|
64
99
|
|
|
65
100
|
```
|
|
66
101
|
$ treex --help
|
|
67
|
-
usage: treex [-h] [-a] [-
|
|
102
|
+
usage: treex [-h] [-a] [-m] [-s] [directory]
|
|
68
103
|
|
|
69
|
-
|
|
104
|
+
List directory contents as a tree with file metadata.
|
|
70
105
|
|
|
71
106
|
positional arguments:
|
|
72
107
|
directory directory to scan (default: current directory)
|
|
73
108
|
|
|
74
109
|
options:
|
|
75
110
|
-h, --help show this help message and exit
|
|
76
|
-
-a, --all show all files
|
|
77
|
-
-w, --width N starting column for file metadata (default: 50)
|
|
111
|
+
-a, --all show all files (including those ignored by Git)
|
|
78
112
|
-m, --modified show file modification times
|
|
113
|
+
-s, --summary show summary only
|
|
79
114
|
```
|
|
80
115
|
|
|
116
|
+
----
|
|
117
|
+
|
|
118
|
+
## Screenshot
|
|
119
|
+
|
|
120
|
+

|
|
121
|
+
|
|
81
122
|
[github-profile]: https://github.com/cgoldberg
|
|
82
123
|
[github-repo]: https://github.com/cgoldberg/treex
|
|
83
124
|
[pypi-home]: https://pypi.org/project/treex-cli
|
|
84
125
|
[mit-license]: https://raw.githubusercontent.com/cgoldberg/treex/refs/heads/main/LICENSE
|
|
85
|
-
[tree-home]: https://oldmanprogrammer.net/source.php?dir=projects/tree
|
treex_cli-0.1.0/README.md
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
# treex
|
|
2
|
-
|
|
3
|
-
## Print a directory tree with file metadata
|
|
4
|
-
|
|
5
|
-
- Copyright (c) 2026 [Corey Goldberg][github-profile]
|
|
6
|
-
- Development: [GitHub][github-repo]
|
|
7
|
-
- Releases: [PyPI][pypi-home]
|
|
8
|
-
- License: [MIT][mit-license]
|
|
9
|
-
|
|
10
|
-
----
|
|
11
|
-
|
|
12
|
-
## About
|
|
13
|
-
|
|
14
|
-
`treex` is a command-line utility (similar to [tree][tree-home]) that recursively
|
|
15
|
-
scans a directory and prints its contents as a tree using Unicode box-drawing
|
|
16
|
-
characters. File names include their human-readable size and, optionally,
|
|
17
|
-
modification time. Text files also include their line count, while binary and
|
|
18
|
-
unreadable files are marked with their type. When Git is installed, it respects
|
|
19
|
-
`.gitignore` rules.
|
|
20
|
-
|
|
21
|
-
Requirements:
|
|
22
|
-
|
|
23
|
-
- Python 3.10+
|
|
24
|
-
- Git 2.0+ (optional)
|
|
25
|
-
- UTF-8-compatible terminal
|
|
26
|
-
|
|
27
|
-
----
|
|
28
|
-
|
|
29
|
-
## Installation
|
|
30
|
-
|
|
31
|
-
Install `treex` from [PyPI][pypi-home] using either `pip` or `pipx`:
|
|
32
|
-
|
|
33
|
-
- `pip install treex-cli`
|
|
34
|
-
- `pipx install treex-cli`
|
|
35
|
-
|
|
36
|
-
----
|
|
37
|
-
|
|
38
|
-
## Usage
|
|
39
|
-
|
|
40
|
-
```
|
|
41
|
-
$ treex --help
|
|
42
|
-
usage: treex [-h] [-a] [-w N] [-m] [directory]
|
|
43
|
-
|
|
44
|
-
print a directory tree with file metadata.
|
|
45
|
-
|
|
46
|
-
positional arguments:
|
|
47
|
-
directory directory to scan (default: current directory)
|
|
48
|
-
|
|
49
|
-
options:
|
|
50
|
-
-h, --help show this help message and exit
|
|
51
|
-
-a, --all show all files, including git-ignored
|
|
52
|
-
-w, --width N starting column for file metadata (default: 50)
|
|
53
|
-
-m, --modified show file modification times
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
[github-profile]: https://github.com/cgoldberg
|
|
57
|
-
[github-repo]: https://github.com/cgoldberg/treex
|
|
58
|
-
[pypi-home]: https://pypi.org/project/treex-cli
|
|
59
|
-
[mit-license]: https://raw.githubusercontent.com/cgoldberg/treex/refs/heads/main/LICENSE
|
|
60
|
-
[tree-home]: https://oldmanprogrammer.net/source.php?dir=projects/tree
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|