ftptui: FTP/SFTP TUI-Client für das Terminal

This commit is contained in:
x3
2026-08-31 14:47:24 +00:00
parent f79d190a47
commit 33827d5598
10 changed files with 1196 additions and 1 deletions
+295 -1
View File
@@ -1,3 +1,297 @@
# ftptui
FTP/SFTP TUI-Client in Python mit SSH-FTP-Unterstützung
> 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** lokales und entferntes Verzeichnis nebeneinander,
Spalten: Name, Größe, Änderungsdatum.
- **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“ (`←`), Doppelklick/`Enter`.
- **Verbindungsprofile** werden als JSON unter `~/.config/ftptui/profiles.json`
gespeichert und können wieder geladen werden.
- Passwortfelder sind abgedunkelt (`password=True`).
- Modernes, terminalfreundliches Layout auf Basis von
[Textual](https://textual.textualize.io/).
---
## 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
```
### 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
| Taste | Aktion |
|------------|---------------------------------|
| `Tab` | Zwischen lokalem/entferntem Paneel wechseln |
| `Enter` | Ordner öffnen / in Datei wechseln |
| `←` | Eine Verzeichnisebene höher |
| `↑ ..` | Eine Ebene hoch (Tabellenzeile) |
| `l` | Auswahl **herunterladen** (entfernt → lokal) |
| `u` | Auswahl **hochladen** (lokal → entfernt) |
| `n` | Neues Verzeichnis anlegen |
| `d` | Auswahl löschen (rekursiv) |
| `r` | Auswahl umbenennen |
| `q` / `Esc`| Beenden |
---
## Projektstruktur
```
ftptui/
├── pyproject.toml # Paketmetadaten, Abhängigkeiten, Einstiegspunkt
├── README.md # diese Dokumentation
├── .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.
---
*Projekt wird innerhalb der `sysdaemon.xyz`-Instanz über Gitea verwaltet
https://git.sysdaemon.xyz/admin/ftptui.*