That's the way, I'm storing recursive dirs to an array.
<?php
public static function getTreeFolders($sRootPath = UPLOAD_PATH_PROJECT, $iDepth = 0) {
$iDepth++;
$aDirs = array();
$oDir = dir($sRootPath);
while(($sDir = $oDir->read()) !== false) {
if($sDir != '.' && $sDir != '..' && is_dir($sRootPath.$sDir)) {
$aDirs[$iDepth]['sName'][] = $sDir;
$aDirs[$iDepth]['aSub'][] = self::getTreeFolders($sRootPath.$sDir.'/',$iDepth);
}
}
$oDir->close();
return empty($aDirs) ? false : $aDirs;
}
?>
dir
(PHP 4, PHP 5)
dir — Retourne une instance de la classe Directory
Description
Un mécanisme pseudo-objet permet la lecture d'un dossier. L'argument directory est ouvert. Deux propriétés sont disponibles une fois le dossier ouvert : le pointeur peut être utilisé avec d'autres fonctions telles que readdir(), rewinddir() et closedir(). Le chemin du dossier est le chemin fourni lors de la construction de l'objet. Trois méthodes sont disponibles : la lecture, la remise à zéro et la fermeture de dossier.
Exemples
Exemple #1 Exemple avec dir()
Notez la façon dont la valeur de retour de dir::read() est vérifiée dans l'exemple suivant. Nous testons si la valeur est identique (égale et de même type que -- voyez opérateurs de comparaison pour plus de détails) FALSE sinon, toute entrée dans le nom serait évalué à FALSE causera l'arrêt de la boucle (exemple, un répertoire nommé 0).
<?php
$d = dir("/etc/php5");
echo "Pointeur : " . $d->handle . "\n";
echo "Chemin : " . $d->path . "\n";
while (false !== ($entry = $d->read())) {
echo $entry . "\n";
}
$d->close();
?>
L'exemple ci-dessus va afficher quelque chose de similaire à :
Pointeur : Resource id #2 Chemin : /etc/php5 . .. apache cgi cli
Notes
Note: L'ordre dans lequel les entrées du dossier sont retournées avec la méthode read dépend de votre système.
dir
20-Oct-2008 12:47
07-Feb-2008 11:45
Here my solution how to do effective recursiv directory listing.
Have fun.
<?php
/**
* example of use:
*/
$d = new RecDir("/etc/",false);
echo "Path: " . $d->getRootPath() . "\n";
while (false !== ($entry = $d->read())) {
echo $entry."\n";
}
$d->close();
class RecDir
{
protected $currentPath;
protected $slash;
protected $rootPath;
protected $recursiveTree;
function __construct($rootPath,$win=false)
{
switch($win)
{
case true:
$this->slash = '\\';
break;
default:
$this->slash = '/';
}
$this->rootPath = $rootPath;
$this->currentPath = $rootPath;
$this->recursiveTree = array(dir($this->rootPath));
$this->rewind();
}
function __destruct()
{
$this->close();
}
public function close()
{
while(true === ($d = array_pop($this->recursiveTree)))
{
$d->close();
}
}
public function closeChildren()
{
while(count($this->recursiveTree)>1 && false !== ($d = array_pop($this->recursiveTree)))
{
$d->close();
return true;
}
return false;
}
public function getRootPath()
{
if(isset($this->rootPath))
{
return $this->rootPath;
}
return false;
}
public function getCurrentPath()
{
if(isset($this->currentPath))
{
return $this->currentPath;
}
return false;
}
public function read()
{
while(count($this->recursiveTree)>0)
{
$d = end($this->recursiveTree);
if((false !== ($entry = $d->read())))
{
if($entry!='.' && $entry!='..')
{
$path = $d->path.$entry;
if(is_file($path))
{
return $path;
}
elseif(is_dir($path.$this->slash))
{
$this->currentPath = $path.$this->slash;
if($child = @dir($path.$this->slash))
{
$this->recursiveTree[] = $child;
}
}
}
}
else
{
array_pop($this->recursiveTree)->close();
}
}
return false;
}
public function rewind()
{
$this->closeChildren();
$this->rewindCurrent();
}
public function rewindCurrent()
{
return end($this->recursiveTree)->rewind();
}
}
?>
28-Nov-2007 08:41
Unlike the others here I've created a function that returns the directory's in a 2-dimensional array. Starting from the requested dir:
<?php
/*
getDirTree(string $dir [, bool $showfiles]);
$dir of the folder you want to list, be sure to have an ending /
$showfiles set to 'false' if files shouldnt be listed in the output array
*/
function getDirTree($dir,$p=true) {
$d = dir($dir);$x=array();
while (false !== ($r = $d->read())) {
if($r!="."&&$r!=".."&&(($p==false&&is_dir($dir.$r))||$p==true)) {
$x[$r] = (is_dir($dir.$r)?array():(is_file($dir.$r)?true:false));
}
}
foreach ($x as $key => $value) {
if (is_dir($dir.$key."/")) {
$x[$key] = getDirTree($dir.$key."/",$p);
}
}
ksort($x);
return $x;
}
?>
Example Output:
Array
(
[folder1] => Array
(
[subfolder1] => Array()
[subfolder2] => Array()
[text.txt] => 1
)
[folder2] => Array()
[folder3] => Array
(
[text.txt] => 1
)
)
26-Jun-2007 12:23
The dir Class, from what I can tell, on a Windows box is not a live image of the directory. When the class is instantiated it takes a snapshot of the directory and then the iterator works off that.
I may be wrong, but when I run two processes that look to see if a directory exists, and then deletes the dir when some processing takes place. Deletes from one process do not effect the iteration of the second.
To get around this I check that the file exists before doing my processing:
$d = dir($dataDir);
while (false !== ($entry = $d->read()))
if ($entry != '..' && $entry != '.' && file_exists("$dataDir\\$entry"))
{
// do stuff
}
$d->close();
I run this as a batch process and can activate it multiple times to process the directory listing in parallel.
-CF
01-Feb-2007 03:10
With SPL, you could recursively list all of the folders inside the current directory like this:
<?php
$it = new RecursiveDirectoryIterator('./');
// RecursiveIteratorIterator accepts the following modes:
// LEAVES_ONLY = 0 (default)
// SELF_FIRST = 1
// CHILD_FIRST = 2
foreach (new RecursiveIteratorIterator($it, 2) as $path) {
if ($path->isDir()) {
echo "$path\n";
}
}
?>
18-Jan-2007 06:17
<?php
$i = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('.'));
?>
works for me..
01-Oct-2006 08:55
IMHO, thats take most effect with smaller number of errors;)
function get_leaf_dirs($dir)
{
$array = array();
$d = @dir($dir);
if($d)
{
while (false !== ($entry = $d->read()))
{
if($entry!='.' && $entry!='..')
{
$entry = $dir.'/'.$entry;
if(is_dir($entry))
{
$subdirs = get_leaf_dirs($entry);
if ($subdirs)
$array = array_merge($array, $subdirs);
else
$array[] = $entry;
}
}
}
$d->close();
}
return $array;
}
24-Aug-2006 02:56
function directoryList($start,$win32=false){
if($win32){
$slash="\\";
}else{
$slash="/";
}
$basename = pathinfo($start);
$basename = $basename['basename'];
$ls=array();
$dir = dir($start);
while($item = $dir->read()){
if(is_dir($start.$slash.$item)&& $item!="." && $item!=".."){
$ls[$basename][]=directoryList($start.$slash.$item,$win32);
}else{
if($item!="."&&$item!=".."){
$ls[$basename][]=$item;
}
}
}
return $ls;
}
$path = pathinfo(__FILE__);
$ls = directoryList($path['dirname'], true);
Regarding samuel's comment about the dir() function not supporting Unicode properly, it's all in the encoding. The function does NOT internally change Unicode characters into question marks (?), as I was first led to believe. If you simply try to output them in UTF-8, they'll show up just right.
24-Jan-2006 07:52
Note that the dir object will use the default encoding for non-unicode programs on Windows with PHP 5.x.
So, if you have a file named with characters unsupported by the current default encoding, the dir->read() method will return a wrong entry.
<?php
/*
** This script is on the same directory than a file named with
** unsupported characters for the current default encoding.
*/
$d = dir("./");
while(false !== ($e = $d->read()))
echo $e . '<br/>';
?>
This will print a "?" for every unsupported characters, and not the right file name. So take care if you check with is_file/is_dir right after enumerating.
13-Jan-2006 09:00
Regarding jaqb's post about a correction to the read_dir function, I have one small fix too if people wish to also list the directories inside this directory and read them into the same array.
<?
function read_dir($dir) {
$array = array();
$d = dir($dir);
while (false !== ($entry = $d->read())) {
if($entry!='.' && $entry!='..') {
$entry = $dir.'/'.$entry;
if(is_dir($entry)) {
$array[] = $entry;
$array = array_merge($array, read_dir($entry));
} else {
$array[] = $entry;
}
}
}
$d->close();
return $array;
}
?>
11-Jan-2006 07:15
Saw the leaf dirs bit... quick mod:
function preg_ls ($path=".", $rec=false, $pat="/.*/") {
$pat=preg_replace ("|(/.*/[^S]*)|s", "\\1S", $pat);
while (substr ($path,-1,1) =="/") $path=substr ($path,0,-1);
if (!is_dir ($path) ) $path=dirname ($path);
if ($rec!==true) $rec=false;
$d=dir ($path);
$ret=Array ();
while (false!== ($e=$d->read () ) ) {
if ( ($e==".") || ($e=="..") ) continue;
if ($rec && is_dir ($path."/".$e) ) {
$ret=array_merge ($ret,preg_ls($path."/".$e,$rec,$pat));
continue;
}
if (!preg_match ($pat,$e) ) continue;
$ret[]=$path."/".$e;
}
return (empty ($ret) && preg_match ($pat,basename($path))) ? Array ($path."/") : $ret;
}
example:
foreach (preg_ls ("/usr/share/fluxbox", true, "/[LT]e[sa]/i") as $file) echo $file."\n";
output:
/usr/share/fluxbox/styles/Leaf/
/usr/share/fluxbox/styles/Clean
/usr/share/fluxbox/styles/Testing/
11-Jan-2006 07:05
This one's pretty nice. After getting frustrated for hunting down .jpg files in my massive music collection (PHP would run out of memory), I thought there should be a preg_ls function.
function preg_ls ($path=".", $rec=false, $pat="/.*/") {
// it's going to be used repeatedly, ensure we compile it for speed.
$pat=preg_replace("|(/.*/[^S]*)|s", "\\1S", $pat);
//Remove trailing slashes from path
while (substr($path,-1,1)=="/") $path=substr($path,0,-1);
//also, make sure that $path is a directory and repair any screwups
if (!is_dir($path)) $path=dirname($path);
//assert either truth or falsehoold of $rec, allow no scalars to mean truth
if ($rec!==true) $rec=false;
//get a directory handle
$d=dir($path);
//initialise the output array
$ret=Array();
//loop, reading until there's no more to read
while (false!==($e=$d->read())) {
//Ignore parent- and self-links
if (($e==".")||($e=="..")) continue;
//If we're working recursively and it's a directory, grab and merge
if ($rec && is_dir($path."/".$e)) {
$ret=array_merge($ret,preg_ls($path."/".$e,$rec,$pat));
continue;
}
//If it don't match, exclude it
if (!preg_match($pat,$e)) continue;
//In all other cases, add it to the output array
$ret[]=$path."/".$e;
}
//finally, return the array
return $ret;
}
Not bad for a mere 18 lines, don't you think?
Example use:
foreach (preg_ls("/etc/X11", true, "/.*\.conf/i") as $file) echo $file."\n";
Output:
/etc/X11/xkb/README.config
/etc/X11/xorg.conf-vesa
/etc/X11/xorg.conf~
/etc/X11/gui.conf
/etc/X11/xorg.conf
/etc/X11/xorg.conf-fbdev
05-Jan-2006 04:24
i've modified the script below to get the leaf folders of any directory (folders with no subfolders).
note: this does not return the folder passed in as a parameter, even if it has no subfolders.
<?php
function get_leaf_dirs($dir) {
$array = array();
$d = dir($dir);
while (false !== ($entry = $d->read())) {
if($entry!='.' && $entry!='..') {
$entry = $dir.'/'.$entry;
if(is_dir($entry)) {
$subdirs = get_leaf_dirs($entry);
if ($subdirs)
$array = array_merge($array, $subdirs);
else
$array[] = $entry;
}
}
}
$d->close();
return $array;
}
?>
