From e9a674afc4232d927bf31474859b803c0ba3ba72 Mon Sep 17 00:00:00 2001 From: Adam Skotarczak Date: Wed, 30 Apr 2025 10:09:22 +0200 Subject: [PATCH 1/3] feature/filepath ready --- pyproject.toml | 4 ++-- scanner.py | 23 +++++++++++++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4e0ff7c..389a410 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [project] -name = "treescanner" +name = "treeScannerASCII" version = "0.1.0" description = "Ein Verzeichnisscanner als CLI-Tool und Python-Modul" authors = [ @@ -8,7 +8,7 @@ authors = [ readme = "README.md" requires-python = ">=3.7" license = { text = "MIT" } -keywords = ["filesystem", "tree", "scanner", "cli", "modul"] +keywords = ["filesystem", "tree", "scanner", "cli", "modul", "markdown"] [build-system] requires = ["setuptools"] diff --git a/scanner.py b/scanner.py index e3e8e5e..266c4c0 100644 --- a/scanner.py +++ b/scanner.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 import os import argparse from typing import Optional, List @@ -13,6 +14,7 @@ class TreeScannerConfig: max_depth (Optional[int]): Maximale Rekursionstiefe. align_comments (bool): Kommentare am Zeilenende ausrichten. language (str): Sprache der Programmausgabe (de oder en). + output_file (str): Pfad und Name der Ausgabedatei. """ def __init__( @@ -20,10 +22,11 @@ class TreeScannerConfig: root_path: str = ".", folder_icon: str = "\U0001F4C1", file_icon: str = "\U0001F4C4", - max_files_per_dir: int = 2, + max_files_per_dir: int = 100, max_depth: Optional[int] = None, align_comments: bool = True, - language: str = "de" + language: str = "de", + output_file: str = "tree.txt" ): self.root_path = root_path self.folder_icon = folder_icon @@ -32,6 +35,7 @@ class TreeScannerConfig: self.max_depth = max_depth self.align_comments = align_comments self.language = language + self.output_file = output_file class TreeScanner: """Klasse zum Scannen von Verzeichnissen und Erzeugen einer ASCII-Baumstruktur.""" @@ -144,23 +148,30 @@ def main(): parser.add_argument("-d", "--max-depth", type=int, help="Maximale Rekursionstiefe; unbegrenzt, wenn nicht gesetzt.") parser.add_argument("--no-align-comments", action="store_false", dest="align_comments", help="Deaktiviert das Ausrichten der Kommentare am Zeilenende.") parser.add_argument("-l", "--language", type=str, default="de", choices=["de", "en"], help="Sprache der Programmausgabe (de oder en).") + parser.add_argument("-o", "--output", type=str, help="Pfad und Name der Ausgabedatei (Standard: tree.txt)") + args = parser.parse_args() + output_file = args.output if args.output else "tree.txt" + output_dir = os.path.dirname(output_file) + if output_dir: + os.makedirs(output_dir, exist_ok=True) + config = TreeScannerConfig( root_path=args.root_path, max_files_per_dir=args.max_files_per_dir, max_depth=args.max_depth, align_comments=args.align_comments, - language=args.language + language=args.language, + output_file=output_file ) scanner = TreeScanner(config) tree_output = scanner.generate_tree() - output_file = "tree.txt" - with open(output_file, "w", encoding="utf-8") as f: + with open(config.output_file, "w", encoding="utf-8") as f: f.write(tree_output + "\n") - scanner.print_summary(output_file) + scanner.print_summary(config.output_file) if __name__ == "__main__": main() From cde91623b71e624ab7fa29d76e8315b4dbfa4419 Mon Sep 17 00:00:00 2001 From: Adam Skotarczak Date: Wed, 30 Apr 2025 10:45:44 +0200 Subject: [PATCH 2/3] feature/ignoredirs --- scanner.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/scanner.py b/scanner.py index 266c4c0..55cd5e7 100644 --- a/scanner.py +++ b/scanner.py @@ -15,6 +15,7 @@ class TreeScannerConfig: align_comments (bool): Kommentare am Zeilenende ausrichten. language (str): Sprache der Programmausgabe (de oder en). output_file (str): Pfad und Name der Ausgabedatei. + ignored_dirs (Optional[List[str]]): Liste von Verzeichnissen, die ignoriert werden sollen. """ def __init__( @@ -26,7 +27,8 @@ class TreeScannerConfig: max_depth: Optional[int] = None, align_comments: bool = True, language: str = "de", - output_file: str = "tree.txt" + output_file: str = "tree.txt", + ignored_dirs: Optional[List[str]] = None ): self.root_path = root_path self.folder_icon = folder_icon @@ -36,6 +38,7 @@ class TreeScannerConfig: self.align_comments = align_comments self.language = language self.output_file = output_file + self.ignored_dirs = ignored_dirs or [] class TreeScanner: """Klasse zum Scannen von Verzeichnissen und Erzeugen einer ASCII-Baumstruktur.""" @@ -75,7 +78,7 @@ class TreeScanner: except PermissionError: return [f"{prefix}└── [Zugriff verweigert] {path}"] - folders = [e for e in entries if os.path.isdir(os.path.join(path, e))] + folders = [e for e in entries if os.path.isdir(os.path.join(path, e)) and e not in self.config.ignored_dirs] files = [e for e in entries if os.path.isfile(os.path.join(path, e))] for idx, folder in enumerate(folders): @@ -148,11 +151,24 @@ def main(): parser.add_argument("-d", "--max-depth", type=int, help="Maximale Rekursionstiefe; unbegrenzt, wenn nicht gesetzt.") parser.add_argument("--no-align-comments", action="store_false", dest="align_comments", help="Deaktiviert das Ausrichten der Kommentare am Zeilenende.") parser.add_argument("-l", "--language", type=str, default="de", choices=["de", "en"], help="Sprache der Programmausgabe (de oder en).") + parser.add_argument( + "--ignore", "-x", + action="append", + help="Verzeichnisse, die ignoriert werden sollen (z. B. .git, __pycache__). Mehrfach verwendbar." + ) + parser.add_argument("-o", "--output", type=str, help="Pfad und Name der Ausgabedatei (Standard: tree.txt)") args = parser.parse_args() output_file = args.output if args.output else "tree.txt" + ignored_dirs = args.ignore if args.ignore else [] + + # Pfad validieren + if not os.path.isdir(args.root_path): + print(f"Fehler: Der angegebene Pfad '{args.root_path}' ist kein gültiges Verzeichnis oder anderer falscher Parameter.") + return + output_dir = os.path.dirname(output_file) if output_dir: os.makedirs(output_dir, exist_ok=True) @@ -163,7 +179,8 @@ def main(): max_depth=args.max_depth, align_comments=args.align_comments, language=args.language, - output_file=output_file + output_file=output_file, + ignored_dirs=ignored_dirs ) scanner = TreeScanner(config) tree_output = scanner.generate_tree() From 365d35abd97f35a26dabad1bd99a54999b1f45c5 Mon Sep 17 00:00:00 2001 From: Adam Skotarczak Date: Wed, 30 Apr 2025 11:41:24 +0200 Subject: [PATCH 3/3] feature/progress --- CHANGELOG.md | 14 +++++++++++++- README.md | 9 +++++++-- VERSION | 2 +- __init__.py | 2 ++ __main__.py | 12 ++++++++++++ scanner.py | 6 ++++++ 6 files changed, 41 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b4eb442..6d1376d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,16 @@ -# CHANGELOG +# CHANGELOG - treeScannerASCII + +- **2025-04-30 Commit v0.3.0** + + - **Geändert:** + - [x] Fortschrittsanzeige beim Scan: Ausgabe alle 5 Sekunden via Timer (TreeScanner.scan_directory) + - [x] Fehlerbehandlung bei ungültigem root_path verbessert (CLI) + - [x] Unterstützung für Ignorierliste von Verzeichnissen (`--ignore`, `-x`), rekursiv wirksam + + - **Hinzugefügt:** + - [x] Unterstützung für Paket-Ausführung via `python -m treeScannerASCII` + - Leeres `__init__.py` beibehalten + - `__main__.py` mit Fallback-Import (`relative` + `direct`) implementiert - **2025-04-27 - Commit v0.2.1** diff --git a/README.md b/README.md index 0a7a2dd..2c0b9d8 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,8 @@ python scanner.py [root_path] [-n N] [-d DEPTH] [--no-align-comments] [-l {de,en | `-d`, `--max-depth` | Maximale Tiefe der Rekursion; unbegrenzt, wenn nicht gesetzt. | | `--no-align-comments` | Deaktiviert die Ausrichtung der Kommentar-Platzhalter am Zeilenende. | | `-l`, `--language` | Sprache der Abschlussmeldung (`de` für Deutsch, `en` für Englisch; Default: `de`). | +| `-x`, `--ignore` | Ignoriert angegebene Verzeichnisse rekursiv (z. B. `.git`, `__pycache__`). Mehrfach möglich. | +| `-o`, `--output` | Zielpfad der Ausgabedatei (z. B. `tree.txt` oder `logs/struktur.txt`) | | `-h`, `--help` | Zeigt diese Hilfe an und beendet das Programm. | **Ausgabe:** @@ -70,6 +72,8 @@ print(output) | `max_depth: Optional[int]` | Ganzzahl oder None | Maximale Rekursionstiefe; `None` = unbegrenzt | | `align_comments: bool` | Bool | Kommentare am Zeilenende ausrichten (Default: `True`) | | `language: str` | String | Sprache der Zusammenfassung (`de` oder `en`) (Default: `de`) | +| `output_file: str` | String | Dateiname und Pfad der Ausgabe-Datei (Default: `tree.txt`) | +| `ignored_dirs: List[str]` | Liste von Strings | Verzeichnisse, die rekursiv ignoriert werden sollen (z. B. `.git`) | ## 📄 Beispielausgabe (tree.txt) @@ -94,13 +98,14 @@ print(output) - Mehrsprachige Abschlussmeldung (Deutsch, Englisch) - Ausgabe als Textdatei (`tree.txt`) - Saubere Google-Style Docstrings für IDE-Kompatibilität +- Fortschrittsanzeige bei großen Scans (alle 5 Sekunden automatische Statusmeldung) +- Ignorieren beliebiger Verzeichnisse rekursiv via `--ignore` +- Konfigurierbarer Ausgabe-Dateiname/-Pfad via `--output` - Modularer Aufbau für spätere Erweiterungen ## 🛡️ Geplante Erweiterungen -- Bessere Fehlerbehandlung bei ungültigem Pfad (anstatt Absturz) - Farbliche Ausgabe der Baumstruktur in der Konsole (optional) -- Konfigurierbare Ausgabe-Datei über CLI - Vorbereitung für Unicode-optimierte Konsolen ## 📄 Lizenz diff --git a/VERSION b/VERSION index f477849..0d91a54 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.2 \ No newline at end of file +0.3.0 diff --git a/__init__.py b/__init__.py index e69de29..710a634 100644 --- a/__init__.py +++ b/__init__.py @@ -0,0 +1,2 @@ +# __init__.py +# (leer) Kennzeichnet das Verzeichnis als Python-Paket \ No newline at end of file diff --git a/__main__.py b/__main__.py index e69de29..596062c 100644 --- a/__main__.py +++ b/__main__.py @@ -0,0 +1,12 @@ +# __main__.py +# (leer) Optional: erlaubt spätere Ausführung mit `python -m treescannerASCII` + +try: + # Für Paket-Ausführung mit `python -m treeScannerASCII` + from .scanner import main +except ImportError: + # Für direkte Ausführung mit `python scanner.py` + from scanner import main + +if __name__ == "__main__": + main() diff --git a/scanner.py b/scanner.py index 55cd5e7..23a2e12 100644 --- a/scanner.py +++ b/scanner.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import os import argparse +import time from typing import Optional, List class TreeScannerConfig: @@ -49,6 +50,7 @@ class TreeScanner: Args: config (TreeScannerConfig): Konfiguration für den Scanner. """ + self.last_output = time.time() self.config = config self.folder_count = 0 self.file_count = 0 @@ -99,6 +101,10 @@ class TreeScanner: for idx, name in enumerate(combined): if not name.startswith("= 5: + print(f"[Info] {self.folder_count + self.file_count} Einträge gescannt...", flush=True) + self.last_output = time.time() + connector = "├── " if idx < len(combined) - 1 else "└── " lines.append(f"{prefix}{connector}{self.config.file_icon} {name}")