$dir = rtrim($dir , ' /\\') . '/';
Ebenfalls ist die Problematik verschiedener Pfadbegrenzen (/ bzw. \) zu berücksichtigen
Unterverzeichnisse rekursiv auslesen
Um im Leseordner auch die Einträge von Unterverzeichnissen zu berücksichtigen, wird ein Teil Funktionalität in eine selbstaufrufende Funktion ausgelagert.
function readDirRecursive($dir)
{
if (false === is_dir($dir)) {
return false;
}
$handle = opendir($dir);
if (false === $handle) {
return false;
}
while (false !== ($file = readdir($handle))) {
// Ausschluss von . und ..
if ('.' == $file || '..' == $file) {
// nächstes Element
continue;
}
// Verarbeitung von Verzeichnisnamen
if (is_dir($dir . $file)) {
// Selbstaufruf
readDirRecursive($dir . $file . '/');
// nächstes Element
continue;
}
// Verarbeitung des Dateinamens, Zuweisung o.ä.
$file;
}
closedir($handle);
return true;
}
$dir = '/path/to/files';
readDirRecursive($dir); Verarbeitung der Inhalte
Bisher wurden die Dateinamen noch nicht weiter verarbeitet. Sollen die Dateinamen nicht direkt ausgegeben werden, sondern bspw. in ein Array eingehen, macht es uns die Funktionskapselung etwas schwieriger. Nachfolgend werden zwei Arten aufgeführt: Die Rückgabe via return und die Nutzung eines referentiellen Parameters.
Grundlage ist bei beiden Lösungen ein Sammeln der Dateinamen im Array $result. Dei Einträge werden dabei in Reihenfolge der Abarbeitung erstellt: Ein an der Leseposition gefundenes Unterverzeichnis wird zuerst durchlaufen (und ggf. weitere in ihm), bevor zur nächsten Position zurückgesprungen wird.
Array Return
Hier ist die Fehlerausgabe FALSE zu beachten, die im Anfang der Funktion erfolgen kann.
function readDirRecursive($dir)
{
if (false === is_dir($dir)) {
return false;
}
$handle = opendir($dir);
if (false === $handle) {
return false;
}
$result = array();
while (false !== ($file = readdir($handle))) {
// Ausschluss von . und ..
if ('.' == $file || '..' == $file) {
// nächstes Element
continue;
}
// Verarbeitung von Verzeichnisnamen
if (is_dir($dir . $file)) {
// Selbstaufruf
$resultSubdir = readDirRecursive($dir . $file . '/');
// gültige Werte dem Rsultset hinzufügen
if (false !== $resultSubdir) {
$result = array_merge($result , $resultSubdir);
}
// nächstes Element
continue;
}
// Array Zuweisung des Dateinamens
$result[] = $file;
}
closedir($handle);
return $result;
}
$dir = '/path/to/files';
$result = readDirRecursive($dir); Referenz-Aufruf
Der Vorteil dieser Funktion: Es muß nicht mit einer Zwischenmenge $resultSubdir gearbeitet werden, da der rekursive Aufruf direkt in die Ergebnismenge schreiben kann. Weiterhin bleibt der Rückgabewert der Funktion frei und könnte bspw. bei einem Verzeichnislesefehler ein entstehendes FALSE bis zum Ur-Aufruf "durchschleifen".
function readDirRecursive($dir , & $result)
{
if (false === is_dir($dir)) {
return false;
}
$handle = opendir($dir);
if (false === $handle) {
return false;
}
while (false !== ($file = readdir($handle))) {
// Ausschluss von . und ..
if ('.' == $file || '..' == $file) {
// nächstes Element
continue;
}
// Verarbeitung von Verzeichnisnamen
if (is_dir($dir . $file)) {
// Selbstaufruf
readDirRecursive($dir . $file . '/' , $result);
// nächstes Element
continue;
}
// Array Zuweisung des Dateinamens
$result[] = $file;
}
closedir($handle);
return true;
}
$dir = '/path/to/files';
$result = array();
readDirRecursive($dir , $result); Anmerkungen
Verzeichnisprüfung
Da die Einträge . und .. in jedem normalen Verzeichnis vorhanden sind und stets als erste Einträge zurückgegeben werden, wird oft statt is_dir ($file) eine alternative Syntax gebraucht: Es werden zwei pauschale readdir ($handle); Aufrufe gestartet, deren Rückgabe nicht verarbeitet wird.
Diese Aufrufe müssen natürlich vor der while Schleife erfolgen.
readdir Rückgabe
Das PHP Manual stellt ausdrücklich in seinem Beispiel die Verwendung von while (false !== ($file = readdir($handle))) als korrekt gegenüber while ($file = readdir($handle)) heraus.
Hintergrund: Nur die Identitätsprüfung (===) bzw. deren Negation nimmt eine explizite Typprüfung vor.
Alle anderen Vergleiche unterscheiden faktisch nicht zwischen NULL, '' (leerer String), 0, '0' etc. Ein Dateiname namens "0" würde hier also bspw. zum Schleifenabbruch führen.
Analog sind die folgenden Schleifenbedingungen falsch:
while (false != ($file = readdir($handle)) {}
while (! false == ($file = readdir($handle)) {} Verzeichnisse auslesen
Natürlich ist auch das Auslesen aller "Nicht-Dateien" (Verzeichnisse) möglich. Dabei kehren sich quasi die Bearbeitung der Zustände is_dir($file) und "restliche" um. Der Selbstaufruf muß natürlich weiterhin für Verzeichniseinträge erfolgen. Relevanter Schleifencode:
while (false !== ($file = readdir($handle))) {
// Ausschluss von . und ..
if ('.' == $file || '..' == $file) {
// nächstes Element
continue;
}
// Verarbeitung von Verzeichnisnamen
if (is_dir($dir . $file)) {
// Verarbeitung des Verzeichnisnamens, Zuweisung o.ä.
$file;
// Selbstaufruf
readDirRecursive($dir . $file . '/');
}
// Else Fall: Für Dateien passiert nichts
}