325 lines
10 KiB
Markdown
325 lines
10 KiB
Markdown
# 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
|
||
```
|
||
|
||
### 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 und entferntem Paneel wechseln |
|
||
| `Enter` | Ordner öffnen (aktiv: fokussiertes Paneel) |
|
||
| `←` / `⌫` | Eine Verzeichnisebene höher |
|
||
| `↑ ..` | Eine Ebene höher (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 |
|
||
|
||
> Hinweis: Hoch-/Herunterladen (`u`/`l`), Anlegen (`n`), Löschen (`d`) und
|
||
> Umbenennen (`r`) wirken auf das **aktive (grün markierte) Paneel**. Wechsel
|
||
> der Seite mit `Tab`.
|
||
|
||
---
|
||
|
||
## 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.
|
||
|
||
---
|
||
|
||
## Changelog
|
||
|
||
### 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.*
|