# ftptui > Interaktiver **FTP- und SFTP-Client** als Terminal-User-Interface in Python. `ftptui` ist ein schlanker, aber vollwertiger Dateibrowser für die Kommandozeile. Er unterstützt klassisches **FTP** (RFC 959, über die Python-Standardbibliothek `ftplib`) sowie **SFTP** (SSH File Transfer Protocol, über `paramiko`). Damit deckt das Tool den überwiegenden Teil der realen Dateiübertragungs-Szenarien ab – einschließlich SSH-basiertem FTP. Das Interface ist zweispaltig aufgebaut: - **links** das lokale Dateisystem, - **rechts** das entfernte System, mit Dateiübertragung in beide Richtungen, rekursivem Hoch-/Herunterladen von Verzeichnissen, Anlegen, Umbenennen und Löschen sowie speicherbaren Verbindungsprofilen. --- ## Inhaltsverzeichnis - [Funktionen](#funktionen) - [Unterstützte Protokolle](#unterstützte-protokolle) - [Installation](#installation) - [Verwendung](#verwendung) - [Tastaturkürzel](#tastaturkürzel) - [Projektstruktur](#projektstruktur) - [Architektur](#architektur) - [Konfiguration & Profile](#konfiguration--profile) - [Entwicklung](#entwicklung) - [Testen](#testen) - [Lizenz](#lizenz) --- ## Funktionen - **Dual-Pane-Dateibrowser** – Layout und Bedienung im Stil von **Total Commander** / **Midnight Commander**: zwei benachbarte Panele (lokal & entfernt) mit den Spalten *Name*, *Größe*, *Datum*, einer Pfadleiste oben, einer Statusleiste unten und grün markiertem aktivem Panel. - **Klassisches Terminal-Thema** – schlanker Dark-Look angelehnt an den Dateimanager **ranger**: schwarzer Hintergrund, Verzeichnisse grün/fett, Auswahl per inverser (hellblauer) Markierung. - **FTP** über die Standardbibliothek, **SFTP** über `paramiko` (SSH-FTP). - **Herunterladen** (`l`) und **Hochladen** (`u`) einzelner Dateien. - **Rekursive Übertragung** kompletter Verzeichnisbäume. - **Verzeichnisse anlegen** (`n`), **umbenennen** (`r`), **löschen** (`d`), rekursives Löschen nicht-leerer Ordner. - **Navigation** mit Maus/Tastatur, „eine Ebene hoch“ (`←`/`⌫`), `Enter` öffnet. - **Verbindungsprofile** werden als JSON unter `~/.config/ftptui/profiles.json` gespeichert und können wieder geladen werden. - Passwortfelder sind abgedunkelt (`password=True`). - Gebaut mit dem terminalfreundlichen TUI-Framework [Textual](https://textual.textualize.io/), ohne fancy Material-Design – ein „echtes“ Konsolenprogramm. --- ## Unterstützte Protokolle | Protokoll | Beschreibung | Bibliothek / Quelle | |-----------|-------------------------------------------|------------------------------------| | `ftp` | Klassisches File Transfer Protocol (RFC 959) | Standard (kein Drittpaket nötig) | | `sftp` | SSH File Transfer Protocol (SSH-FTP) | `paramiko` | > **Hinweis:** „SSH-FTP“ kann zweierlei bedeuten – das SFTP-Subsystem über eine > SSH-Schicht (hier umgesetzt) oder FTP über einen SSH-Tunnel (sog. „FTP over > SSH“). In `ftptui` wird **SFTP über SSH** unterstützt, der heute übliche und > sichere Weg. --- ## Installation ### Voraussetzungen - Python **≥ 3.10** - `pip` und idealerweise eine virtuelle Umgebung ### Aus dem Quellverzeichnis ```bash # virtuelle Umgebung anlegen und aktivieren python3 -m venv .venv source .venv/bin/activate # Abhängigkeiten installieren pip install -e . # Abhängigkeiten (nur Laufzeit): # textual - TUI-Framework # paramiko - SFTP/SSH ``` ### Installations- & Deinstallations-Skripte (systemweit) Im Projektverzeichnis liegen zwei Scripts für eine **systemweite Installation** auf Debian/Ubuntu (PEP 668 „externally managed“ wird berücksichtigt: es wird eine eigene Umgebung unter `/opt/ftptui/venv` angelegt und nach `/usr/local/bin/ftptui` verlinkt): ```bash ./install.sh # systemweit installieren (fragt ggf. nach sudo) ./install.sh --force # erneut installieren/aktualisieren ./uninstall.sh # systemweite Installation entfernen (Nutzdaten bleiben) ./uninstall.sh --purge # zusätzlich Konfigurationsdateien löschen ``` Nach `./install.sh` steht das Kommando `ftptui` global im PATH bereit. ### Als Paket ```bash pip install . ``` ### Als installiertes Kommando Nach `pip install -e .` steht das Kommando `ftptui` global in der Umgebung bereit: ```bash ftptui ``` --- ## Verwendung 1. Starten: `ftptui` 2. Im **Verbindungsbildschirm** die Daten eingeben: - **Verbindungsprofil** – ein zuvor gespeichertes Profil auswählen, oder ein neues anlegen. - **Protokoll** – `sftp` (SSH) oder `ftp`. - **Host**, **Port** (SFTP-Vorgabe `22`, FTP-Vorgabe `21`), **Benutzer**, **Passwort**. - Auf **Verbinden** klicken. Der Port wird bei Protokollwechsel automatisch auf den jeweiligen Standard gesetzt. 3. Nach erfolgreicher Verbindung erscheint der **Browser-Bildschirm** mit zwei Panelen: - links `/` des lokalen Rechners bzw. das Home-Verzeichnis, - rechts das Home-/Root-Verzeichnis des entfernten Systems. 4. Zwischen den Paneelen wechseln mit `Tab`. Die fokussierte Tabelle erhält die Aktionen (Hoch-/Herunterladen, Umbenennen, Löschen …). > **Tipp:** Die Aktionen `u`/`l` wirken auf das gerade **in der fokussierten > Tabelle** angewählte Element und übertragen in die jeweils andere Seite. --- ## Tastaturkürzel ### Dateibrowser | Taste | Aktion | |--------------|---------------------------------| | `Tab` | Zwischen lokalem und entferntem Paneel wechseln | | `↑` / `↓` | Zeilenauswahl bewegen | | `→` | Ordner öffnen / Datei ansehen | | `←` / `⌫` | Eine Verzeichnisebene höher | | `Enter` | Ordner öffnen, Datei im Betrachter anzeigen | | `↑ ..` | Eine Ebene höher (Tabellenzeile) | | `Leertaste` | Eintrag **markieren/abwählen** (Cursor rückt weiter) | | `Strg`+`A` | Alle Einträge markieren / Markierung aufheben | | `Esc` | Markierung des aktiven Paneels aufheben | | `v` | Datei im Betrachter anzeigen | | `l` | **Herunterladen** (entfernt → lokal) | | `u` | **Hochladen** (lokal → entfernt) | | `n` | Neues Verzeichnis anlegen | | `d` | Löschen (rekursiv) | | `r` | Umbenennen | | `q` | Beenden | > Hinweis: Hoch-/Herunterladen (`u`/`l`), Löschen (`d`) und Umbenennen (`r`) > wirken auf das **aktive (grün markierte) Paneel**. Wechsel der Seite mit `Tab`. > Die Pfeiltasten `→`/`←` navigieren die Verzeichnisstruktur (öffnen / eine > Ebene hoch), `↑`/`↓` bewegen die Zeilenauswahl. #### Mehrfachauswahl Mit der `Leertaste` markierte Einträge werden **fett und gelb** dargestellt; die Pfadleiste oben zeigt an, wie viele Einträge je Paneel markiert sind. Liegt eine Markierung vor, arbeiten `l`, `u` und `d` auf **allen markierten Einträgen**, sonst auf dem Eintrag unter dem Cursor. Nach dem Transfer bzw. beim Verzeichniswechsel wird die Markierung zurückgesetzt. ### Datei-Betrachter `Enter` oder `v` auf einer Datei öffnet sie mit Syntax-Hervorhebung; die Sprache wird über Pygments anhand der Endung erkannt (`.txt`, `.md`, `.py`, `.cpp`, `.json`, `.yml`, …). Entfernte Dateien werden dafür in eine Temporärdatei geladen und danach wieder entfernt. Binärdateien und Dateien über 2 MiB werden abgelehnt statt angezeigt. | Taste | Aktion | |------------------|-----------------------------| | `Esc` / `q` | Betrachter schließen | | `↑` / `↓` | Zeilenweise blättern | | `Bild↑` / `Bild↓`| Seitenweise blättern | | `Pos1` / `Ende` | Anfang / Ende | | `w` | Zeilenumbruch umschalten | | `l` | Zeilennummern umschalten | ### Verbindungsdialog | Taste | Aktion | |--------------|---------------------------------| | `↑` / `↓` | Zwischen den Eingabefeldern wechseln | | `Tab` | Nächstes Feld | | `Enter` | In einem Eingabefeld: verbinden; in einer Auswahlliste: Liste öffnen | | `Strg`+`S` | Profil speichern | | `Esc` | Beenden | --- ## Projektstruktur ``` ftptui/ ├── pyproject.toml # Paketmetadaten, Abhängigkeiten, Einstiegspunkt ├── README.md # diese Dokumentation ├── install.sh # systemweite Installation (/opt/ftptui/venv) ├── uninstall.sh # Deinstallation systemweiter Installation ├── .gitignore └── ftptui/ ├── __init__.py # Versionsnummer ├── app.py # Textual-TUI: Verbindungs- & Browser-Bildschirme ├── backend.py # Fabrik: wählt FTP- oder SFTP-Transport ├── config.py # Speicherung/Laden der Verbindungsprofile (JSON) ├── models.py # Datentypen & Transport-Protokoll ├── ftp_backend.py # FTP-Adapter (ftplib) └── sftp_backend.py # SFTP-Adapter (paramiko) ``` --- ## Architektur Die App trennt **Oberfläche** (Textual) von **Transport** (Netzwerkprotokolle) durch ein kleines Protokoll/Interface: - `FileTransferBackend` (in `models.py`) definiert die gemeinsame API. - `FTPBackend` und `SFTPBackend` implementieren sie. - `create_backend(protocol)` in `backend.py` liefert den passenden Adapter. Gemeinsame Schnittstelle (Auszug): ```python def connect(host, port, username, password) -> None def listdir(path) -> list[RemoteEntry] def chdir(path) / pwd() -> str def download(remote, local) -> None def upload(local, remote) -> None def mkdir(path) / remove / rmdir / rename def close() -> None ``` `RemoteEntry` beschreibt einen Eintrag mit `name`, `kind` (`file`/`dir`), `size` und `modified`. Dadurch kann die Oberfläche unabhängig vom Protokoll arbeiten – das Hinzufügen weiterer Backends (z. B. WebDAV) ist ohne Änderung der UI möglich. ### Pfadbehandlung Beide Backends normalisieren Pfade zu **absoluten** Angaben relativ zum Root des entfernten Systems. FTP-Operationen setzen das Arbeitsverzeichnis vor einer Aktion auf `/`, sodass Dateiübertragungen unabhängig vom zuletzt betrachteten Ordner zuverlässig funktionieren. SFTP nutzt absolute Pfade direkt. ### Profilwertung Profile werden als JSON in `~/.config/ftptui/profiles.json` (bzw. `$XDG_CONFIG_HOME/ftptui/profiles.json`) gespeichert. Das Passwort wird nur abgelegt, wenn es entsprechend markiert wurde (aktuell standardmäßig direkt gespeichert – Datenschutz-Hinweis siehe unten). --- ## Konfiguration & Profile Profile speichern: im Verbindungsbildschirm Daten eingeben und **Profil speichern** drücken. Gespeicherte Einträge erscheinen künftig im Dropdown **Verbindungsprofil**. Beispieldatei `~/.config/ftptui/profiles.json`: ```json [ { "name": "git.sysdaemon.xyz", "protocol": "sftp", "host": "git.sysdaemon.xyz", "port": 22, "username": "user", "password": "", "save_password": false }, { "name": "backup-server", "protocol": "ftp", "host": "backup.local", "port": 21, "username": "ftpuser", "password": "secret", "save_password": true } ] ``` > **Sicherheitshinweis:** Speichern Sie Passwörter in Profilen nur auf > vertrauenswürdigen Systemen. Die Datei liegt im Klartext im Benutzerverzeichnis. --- ## Entwicklung ```bash # Umgebung python3 -m venv .venv && source .venv/bin/activate pip install -e . "textual>=0.80.0" "paramiko>=3.4.0" # Laufzeit prüfen python -c "import ftptui; print(ftptui.__version__)" # App booten (Konsolen-Test) ftptui ``` ### Code-Stil & Qualität - Typannotationen (`from __future__ import annotations`) durchgängig. - Protokoll-/Interface-basierte Implementierung mit `typing.Protocol`. - Keine Abhängigkeit auf Drittanbieter außer `textual` und `paramiko`. --- ## Testen Die Backends werden gegen **lokale Testserver** end-to-end getestet: - **FTP** gegen `pyftpdlib` (nur für Tests; nicht Teil der Laufzeit-Abhängigkeiten), - **SFTP** gegen eine eigene `paramiko`-SSH-Server-Implementierung. Ablauf der Tests: Verbinden, Listings, Download, Upload, `mkdir`, `rename`, `remove`, rekursives `rmdir`, `close` – für beide Protokolle. ```bash pip install pyftpdlib python tests/test_backends.py # Beispieldatei (siehe Entwicklung/Skripte) ``` > Ein ausführbares Testskript kann ergänzt und an dieser Stelle dokumentiert > werden; die Backends sind derart modular, dass sie ohne Terminal getestet > werden können. --- ## Lizenz MIT – siehe Projektträger/Repositories. Keine gewerblichen Einschränkungen. --- ## Changelog ### v0.3.0 - **Bugfix (Pfeil-Navigation):** Im Dateibrowser navigieren die Pfeiltasten nun im File-Manager-Stil: `←` wechselt eine Ebene nach oben, `→` öffnet den markierten Eintrag, `↑`/`↓` bewegen die Auswahl. Zuvor verschluckte das `DataTable`-Widget die Tasten (Widget-Bindings haben Vorrang). Dafür wird die neue `FileTable`-Klasse genutzt, die `left`/`right` passend umbindet. - **Bugfix (Tab-Panel-Wechsel):** `Tab` wechselt jetzt zuverlässig zwischen dem lokalen und dem entfernten Paneel (explizite `action_focus_next` statt unzuverlässigem `focus_next`). - **Bugfix (`_selected`):** Die Auswahlauswertung liefert jetzt die Klartext-Zeichenkette statt eines `rich.Text`-Objekts, wodurch Öffnen/Enter nicht mehr mit `AttributeError` abstürzte. - **Neu:** `install.sh` / `uninstall.sh` für systemweite Installation (PEP-668-konform via `/opt/ftptui/venv` + `/usr/local/bin/ftptui`). ### v0.2.0 - **Bugfix:** Wechsel in den Browser-Bildschirm korrigiert (`set_screen` → `switch_screen`). Vorher führte eine erfolgreiche Verbindung in einen `AttributeError` und der FTP/SFTP-Client beendete sich. - **Theme:** Umstellung auf ein klassisches Terminal-Design im Stil von **ranger** (Dark-Look, grün/fette Verzeichnisse, inverse Auswahl). - **Layout:** Neuaufbau als **Total-Commander-artiger** Dual-Pane-Browser mit Pfadleiste oben, Statusleiste unten und grün markiertem aktivem Panel. - Datums-Spalte wird nun als lesbares Datum (`YYYY-MM-DD HH:MM`) angezeigt. ### v0.1.0 - Erste Veröffentlichung: FTP- & SFTP-Backends, TUI, Verbindungsprofile. --- *Projekt wird innerhalb der `sysdaemon.xyz`-Instanz über Gitea verwaltet – https://git.sysdaemon.xyz/x3/ftptui.*