ftp_mlsd()
PHP ftp_mlsd(): FTP-Verzeichnisse strukturiert auflisten. Syntax, Rückgabewerte, Beispiele und Fehlerbehandlung.
Was ist ftp_mlsd()?
ftp_mlsd() ist eine eingebaute PHP-Funktion (verfügbar seit PHP 7.2), die den Inhalt eines Verzeichnisses auf einem FTP-Server mithilfe des FTP-Befehls MLSD auflistet. Anders als ältere Listenfunktionen liefert sie ein strukturiertes, maschinenlesbares Ergebnis: Anstelle eines rohen Textblocks, den Sie selbst parsen müssen, erhalten Sie ein array von Einträgen, bei dem jede Datei oder jedes Verzeichnis benannte Attribute wie Typ, Größe und Änderungszeit enthält.
Das ist wichtig, weil Verzeichnislisten von FTP-Servern notorisch inkonsistent sind — ftp_rawlist() gibt Zeilen zurück, deren Format vom Betriebssystem des Servers abhängt. MLSD wurde zum FTP-Protokoll (RFC 3659) genau hinzugefügt, um dies zu standardisieren, und ftp_mlsd() stellt es direkt zur Verfügung.
Verwenden Sie ftp_mlsd(), wenn Sie:
- Dateien aufzählen und die Größe, den Typ oder den Zeitstempel jeder einzelnen Datei kennen möchten.
- Verzeichnisse zuverlässig von Dateien unterscheiden müssen (das Attribut
typeerledigt das für Sie). - Die fehleranfällige String-Analyse vermeiden möchten, die
ftp_rawlist()erfordert.
Wenn Sie nur eine flache Liste von Dateinamen benötigen, ist ftp_nlist() einfacher. Wenn Sie Server vor PHP 7.2 oder Server ohne MLSD-Unterstützung unterstützen müssen, weichen Sie auf ftp_rawlist() aus.
Syntax von ftp_mlsd()
ftp_mlsd(FTP\Connection $ftp, string $directory): array|falseDie Funktion benötigt zwei erforderliche Parameter:
| Parameter | Beschreibung |
|---|---|
$ftp | Die FTP-Verbindungskennung, die von ftp_connect() (oder ftp_ssl_connect()) zurückgegeben wird. |
$directory | Der Pfad des aufzulistenden Verzeichnisses, z. B. /public_html oder . für das aktuelle Verzeichnis. |
Beide Parameter sind erforderlich. Der Befehl MLSD operiert immer auf einem expliziten Pfad — übergeben Sie ., wenn Sie das aktuelle Verzeichnis meinen.
Bei Erfolg gibt die Funktion ein array von Einträgen zurück, bei einem Fehler false (beispielsweise wenn der Pfad nicht existiert oder der Server MLSD nicht unterstützt).
Was ftp_mlsd() zurückgibt
Jedes Element des zurückgegebenen arrays ist ein assoziatives array, das einen Eintrag beschreibt. Die genauen Schlüssel hängen davon ab, was der Server meldet, aber die häufigsten sind:
| Schlüssel | Bedeutung |
|---|---|
name | Der Name der Datei oder des Verzeichnisses. |
type | Der Eintragstyp: file, dir, cdir (aktuelles Verzeichnis, .) oder pdir (übergeordnetes Verzeichnis, ..). |
size | Größe in Bytes (normalerweise nur für Dateien vorhanden). |
modify | Zeitstempel der letzten Änderung, formatiert als YYYYMMDDHHMMSS. |
perms | Berechtigungsstring, wie vom Server gemeldet. |
unique | Ein vom Server zugewiesener Bezeichner, der pro Datei eindeutig ist. |
Ein einzelner Eintrag sieht so aus:
[
'name' => 'report.pdf',
'type' => 'file',
'size' => '20480',
'modify' => '20240115093000', // 2024-01-15 09:30:00
'perms' => 'adfr',
]Verwendung von ftp_mlsd()
Bevor Sie etwas auflisten, verbinden Sie sich mit ftp_connect() und authentifizieren sich mit ftp_login(). Der vollständige Ablauf sieht so aus:
<?php
// 1. Open a connection
$ftp = ftp_connect('ftp.example.com');
// 2. Authenticate
ftp_login($ftp, 'username', 'password');
// 3. Switch to passive mode (recommended behind firewalls/NAT)
ftp_pasv($ftp, true);
// 4. Get a structured listing of the directory
$entries = ftp_mlsd($ftp, '/public_html');
// 5. Always close the connection when done
ftp_close($ftp);Über die Liste iterieren
Der eigentliche Wert von ftp_mlsd() liegt in den strukturierten Daten. Hier geben wir jede Datei mit einer menschenlesbaren Größe aus und überspringen die Pseudo-Einträge . und ..:
<?php
$entries = ftp_mlsd($ftp, '.');
foreach ($entries as $entry) {
// Skip the current-dir and parent-dir markers
if (in_array($entry['type'], ['cdir', 'pdir'], true)) {
continue;
}
if ($entry['type'] === 'dir') {
echo "[DIR] {$entry['name']}\n";
} else {
$kb = round($entry['size'] / 1024, 1);
echo "[FILE] {$entry['name']} ({$kb} KB)\n";
}
}Das Feld modify ist ein 14-stelliger Zeitstempel. Sie können ihn mit DateTime in ein echtes Datum umwandeln:
<?php
$modified = DateTime::createFromFormat('YmdHis', $entry['modify']);
echo $modified->format('Y-m-d H:i:s');Fehlerbehandlung in ftp_mlsd()
ftp_mlsd() gibt bei einem Fehler false zurück, daher sollten Sie das Ergebnis immer prüfen, bevor Sie darüber iterieren — der Aufruf von foreach auf false würde eine Warnung ausgeben und nichts verarbeiten.
<?php
$entries = ftp_mlsd($ftp, '/path/that/may/not/exist');
if ($entries === false) {
echo "Failed to retrieve the directory listing.\n";
} else {
foreach ($entries as $entry) {
echo $entry['name'] . "\n";
}
}Verwenden Sie den strikten Vergleich === false. Ein leeres Verzeichnis gibt ein leeres array [] zurück, das falsy ist — eine lockere Prüfung mit if (!$entries) würde ein leeres (aber gültiges) Verzeichnis fälschlicherweise als Fehler behandeln.
Häufige Gründe, warum ftp_mlsd() fehlschlägt:
- Der Server unterstützt den Befehl
MLSDnicht (ältere oder minimale FTP-Server). Weichen Sie aufftp_rawlist()aus. - Der Verzeichnispfad ist falsch oder Sie haben keine Berechtigung, ihn zu lesen.
- Sie sind noch nicht eingeloggt oder die Verbindung ist abgelaufen.
ftp_mlsd() im Vergleich zu anderen Listenfunktionen
| Funktion | Gibt zurück | Am besten geeignet für |
|---|---|---|
ftp_mlsd() | Strukturiertes array (name, type, size, modify…) | Zuverlässige Metadaten über Server hinweg (PHP 7.2+) |
ftp_nlist() | Flaches array von Namen | Eine schnelle Liste von Dateinamen |
ftp_rawlist() | array von rohen ls-Zeilen | Ältere Server ohne MLSD |
Fazit
ftp_mlsd() ist die moderne, zuverlässige Methode, um ein FTP-Verzeichnis in PHP aufzulisten: Sie erhalten ein strukturiertes array mit dem Typ, der Größe und der Änderungszeit jedes Eintrags, was Sie vor dem fehleranfälligen Textparsen bewahrt, das ältere Funktionen erfordern. Kombinieren Sie es mit ftp_connect(), ftp_login() und ftp_close() für einen vollständigen, robusten FTP-Listing-Workflow — und denken Sie daran, vor dem Iterieren auf === false zu prüfen.