dir

(PHP 3, PHP 4, PHP 5)

dir -- directory 类

说明

class dir {

dir ( string directory )

string path

resource handle

string read ( void )

void rewind ( void )

void close ( void )

}

这是个仿冒面向对象的机制来读取一个目录。给定的 directory 被打开。一旦目录被打开,有两个属性可用。handle 属性可以用在其它目录函数例如 readdir()rewinddir()closedir() 中。path 属性被设为被打开的目录路径。有三个方法可用:read,rewind 和 close。

范例

例子 1. dir() 例子

请留意下面例子中检查 dir() 返回值的风格。我们明确地测试返回值是否全等于(值和类型都相同 - 更多信息参见比较运算符FALSE,否则任何目录项的名称求值为 FALSE 的都会导致循环停止。

<?php
$d
= dir("/etc/php5");
echo
"Handle: " . $d->handle . "\n";
echo
"Path: " . $d->path . "\n";
while (
false !== ($entry = $d->read())) {
   echo
$entry."\n";
}
$d->close();
?>

上例的输出类似于:

Handle: Resource id #2
Path: /etc/php5
.
..
apache
cgi
cli

注释

注: read 方法返回的目录项的顺序依赖于系统。

注: 本函数定义了内部类 Directory,意味着不能再用同样的名字定义用户自己的类。PHP 预定义类的完整列表见预定义类一节。


add a note add a note User Contributed Notes
alex at snet-group dot org
02-Oct-2006 02: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;
     }
done_to_death at example dot com
24-Aug-2006 08: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);
23-Feb-2006 05:02
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.
samuel dot l at mushicrew dot com
25-Jan-2006 02: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.
radar at frozenplague dot net
13-Jan-2006 04: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;
}
?>
fordiman at gmail dot com
11-Jan-2006 02: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/
fordiman at gmail dot com
11-Jan-2006 02: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
Anton Backer
05-Jan-2006 11: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;
}
?>