scandir

(PHP 5)

scandir -- 列出指定路径中的文件和目录

说明

array scandir ( string directory [, int sorting_order [, resource context]] )

返回一个 array,包含有 directory 中的文件和目录。

参数

directory

要被浏览的目录

sorting_order

默认的排序顺序是按字母升序排列。如果使用了可选参数 sorting_order(设为 1),则排序顺序是按字母降序排列。

context

context 参数的说明见手册中的 Streams API 一章。

返回值

成功则返回包含有文件名的 array,如果失败则返回 FALSE。如果 directory 不是个目录,则返回布尔值 FALSE 并生成一条 E_WARNING 级的错误。

范例

例子 1. 一个简单的 scandir() 例子

<?php
$dir    
= '/tmp';
$files1 = scandir($dir);
$files2 = scandir($dir, 1);

print_r($files1);
print_r($files2);
?>

上例的输出类似于:

Array
(
    [0] => .
    [1] => ..
    [2] => bar.php
    [3] => foo.txt
    [4] => somedir
)
Array
(
    [0] => somedir
    [1] => foo.txt
    [2] => bar.php
    [3] => ..
    [4] => .
)

例子 2. scandir() 在 PHP 4 中的实现

<?php
$dir
= "/tmp";
$dh  = opendir($dir);
while (
false !== ($filename = readdir($dh))) {
    
$files[] = $filename;
}

sort($files);

print_r($files);

rsort($files);

print_r($files);

?>

上例的输出类似于:

Array
(
    [0] => .
    [1] => ..
    [2] => bar.php
    [3] => foo.txt
    [4] => somedir
)
Array
(
    [0] => somedir
    [1] => foo.txt
    [2] => bar.php
    [3] => ..
    [4] => .
)

注释

提示: 如果“fopen wrappers”已经被激活,则在本函数中可以把 URL 作为文件名来使用。请参阅 fopen() 函数来获取怎样指定文件名的详细信息以及支持 URL 封装协议的列表:附录 L


add a note add a note User Contributed Notes
reeded2002 at mypacks dot net
28-Oct-2006 12:54
In response to phpfeedback.e.stevegs, if you want to emulate the page displayed by an absent index completely I think this is more accurate:

<?php
  
echo '<h1>Index of /adult/</h1>';
   echo
'<ul>';
   echo
'<li><a href="/"> Parent Directory</a></li>';

  
$dir = scandir('.');
  
$files = count( $dir );
   for (
$i = 0; $i < $files; $i++ )
   {
       if (
is_file($dir[$i]) )
           echo
"<li><a href=\"$dir[$i]\">$dir[$i]</a></li><br>";

       if (
is_dir($dir[$i]) )
           echo
"<li><a href=\"$dir[$i]\"/>$dir[$i]/</a></li><br>";
   }

   echo
'</ul>';
?>

If the directory happens to be the root you'ld want to leave off the Parent Directory line. It's easy to apply filters to this. What I'm using filters out filenames of a certain length, any non-html and non-php files, and also various other files and directories I just dont' want being shown:

<?php
  
echo '<h1>Index of /adult/</h1>';
   echo
'<ul>';
   echo
'<li><a href="/"> Parent Directory</a></li>';

  
$dir = scandir('.');
  
$files = count( $dir );
   for (
$i = 0; $i < $files; $i++ )
   {
       if (
is_file($dir[$i]) && strlen( $dir[$i] ) <= 36 && ( strstr( strtolower( $dir[$i] ), '.htm' ) ||  strstr( strtolower( $dir[$i] ), '.html' ) ||  strstr( strtolower( $dir[$i] ), '.php' ) ) )
           echo
"<li><a href=\"$dir[$i]\">$dir[$i]</a></li><br>";

       if (
is_dir($dir[$i])  && $dir[$i] != "." && $dir[$i] != ".." && $dir[$i] != "adult" )
           echo
"<li><a href=\"$dir[$i]\"/>$dir[$i]/</a></li><br>";
   }

   echo
'</ul>';
?>
phpfeedback dot e dot stevegs at spamgourmet dot com
15-Aug-2006 10:18
Perhaps I'm missing something, but none of the other suggestions shown here did what I wanted.

The problem was I wanted to list all files on a hidden (ie. unreferenced) directory on my web site.  Normally, if there's no INDEX.HTM, this will happen automatically.  However, my service provider is a bit smarter: they throw up an 'unauthorised user' message in the absence of the INDEX.HTM.  The following got round the problem - if the directory contents alter, the changes are shown automatically.

Sorry about the HTML tags below - it was the only way I could get the preview to display properly.

Two files are required:

1) a blank INDEX.HTM that calls LISTFILE.PHP in a single frame:

 <HTML>
 <HEAD>
 </HEAD>

 <FRAMESET ROWS="100%" FRAMEBORDER=no BORDER=0 FRAMESPACING="0">
 <FRAME src="listfile.php">
 </FRAMESET></HTML>

2) a LISTFILE.PHP that lists all files and subdirectories in the current web directory (*except* the INDEX.HTM and LISTFILE.PHP files, which you know are there!)
Links to all these files are automatically created:

 <HTML>
 <HEAD>
 </HEAD>

 <BODY>
<?php
if ($handle = opendir('.')) {
  while (
false !== ($file = readdir($handle)))
  {
   if (
$file != "." && $file != ".." && $file != "index.htm"
    
&& $file != "listfile.php")
       echo
"<a href=\"$file\">$file</a><br>";
  }
 
closedir($handle);
}
?>
 </BODY></HTML>

Regards,

Steve Glennie-Smith
beingmrkenny at gmail dot com
14-Aug-2006 02:41
I wrote this function to read a folder and place all the folders and sub folders it contains into an array.

<?php

// Initialise empty array, otherwise an error occurs
$folders = array();

function
recursive_subfolders($folders) {

  
// Set path here
  
$path = '/path/to/folder';
  
  
// Create initial "Folders" array
  
if ($dir = opendir($path)) {
      
$j = 0;
       while ((
$file = readdir($dir)) !== false) {
           if (
$file != '.' && $file != '..' && is_dir($path.$file)) {
              
$j++;
              
$folders[$j] = $path . $file;
           }
       }
   }
  
  
closedir($dir);
  
  
// Then check each folder in that array for subfolders and add the subfolders to the "Folders" array.
  
$j = count($folders);
   foreach (
$folders as $folder) {
       if (
$dir = opendir($folder)) {
           while ((
$file = readdir($dir)) !== false) {
              
$pathto = $folder. '/' . $file;
               if (
$file != '.' && $file != '..' && is_dir($pathto) && !in_array($pathto, $folders)) {
                  
$j++;
                  
$folders[$j] = $pathto;
                  
$folders = recursive_subfolders($folders);
               }
           }
       }
      
closedir($dir);
   }
  
  
sort($folders);
   return
$folders;
}

$folders = recursive_subfolders($folders);

?>

$folders now contains an array with the full paths to each subfolder. E.g.:

Array
(
   [0] => /path/to/folder/dir1
   [1] => /path/to/folder/dir1/subdir
   [2] => /path/to/folder/dir1/subdir/subsubdir
   [3] => /path/to/dolfer/dir2
)

This function has only been tested on Linux.
at_he at hotma1l dot com
10-Aug-2006 03:50
you can separate DIRS from FILES in two arrays with a little script like :D ...

<?php

$files
= scandir ( $dir ) ;

foreach(
$files as $pos => $file ) {

   if(
is_dir( $file ) ) {
      
      
$dirs[] = $file ;
       unset(
$files[$pos] ) ;
   }
}

?>
malmsteenforce at tlen dot pl
20-Jul-2006 03:55
This function is recursive version of scandir, it scans all directories inside given directory. For instance : if we give path './dir1/' as argument , function will find also /dir1/dir2/file etc. - everything what`s inside given directory.

function scandir_recursive($path)
{
if (!is_dir($path)) return 0;
$list=array();
$directory = @opendir("$path"); // @-no error display
while ($file= @readdir($directory))
  {
       if (($file<>".")&&($file<>".."))
       { 
           $f=$path."/".$file;
$f=preg_replace('/(\/){2,}/','/',$f); //replace double slashes
if(is_file($f)) $list[]=$f;           
if(is_dir($f))
$list = array_merge($list ,scandir_recursive($f));  //RECURSIVE CALL                             
       }   
   }
@closedir($directory); 
return $list ;
}
greg at sasses dot net
19-May-2006 03:27
A minor revision to elbekko at gmail dot com <PHP5 scandir function. The arsort should be rsort. Here is the complete function with the correction:

<?php
if(!function_exists('scandir')) {
   function
scandir($dir, $sortorder = 0) {
       if(
is_dir($dir))        {
          
$dirlist = opendir($dir);
           while( (
$file = readdir($dirlist)) !== false) {
               if(!
is_dir($file)) {
                  
$files[] = $file;
               }
           }
           (
$sortorder == 0) ? asort($files) : rsort($files); // arsort was replaced with rsort
          
return $files;
       } else {
       return
FALSE;
       break;
       }
   }
}
?>
elbekko at gmail dot com
08-Apr-2006 07:34
Scandir function for php 3 and up.

<?php
//
// Scandir for PHP4
//
if(!function_exists('scandir'))
{
   function
scandir($dir, $sortorder = 0)
   {
       if(
is_dir($dir))
       {
          
$dirlist = opendir($dir);
          
           while( (
$file = readdir($dirlist)) !== false)
           {
               if(!
is_dir($file))
               {
                  
$files[] = $file;
               }
           }
          
           (
$sortorder == 0) ? asort($files) : arsort($files);
          
           return
$files;
       }
       else
       {
       return
FALSE;
       break;
       }
   }
}
?>
www.mdsjack.bo.it
08-Apr-2006 02:54
I would like to share a couple of functions I've made to get an Array of files of a certain extension inside a Directory.

<?php

// Firstly, a PHP 5 emulation

function php4_scandir($dir, $sort = 0)
{
   if (
PHP_VERSION >= '5') return scandir($dir, $sort);
  
  
$dirmap = array();
  
   if(!
is_dir($dir))
   {
      
trigger_error("lib::scandir($dir): failed to open dir: Invalid argument", E_USER_WARNING);
       return
false;
   }
  
  
$dir = opendir($dir);
  
   while (
false !== ($file = readdir($dir)))
      
$dirmap[] = $file;
  
  
closedir($dir);
  
   (
$sort == 1) ? rsort($dirmap) : sort($dirmap);
  
   return
$dirmap;
}

/*
Then, this one converts directory files into array items.
It also can filter by file extension.
*/

function dir2arr($dir, $ext = null)
{
  
$arr = array();
  
   if(
PHP_VERSION >= '4.3.0')
   {
      
# PHP 4.3.0 code
      
if ($dir = glob("$dir*".(!$ext ? '.*' : '{'.$ext.', '.strtoupper($ext).'}'), GLOB_NOSORT + GLOB_BRACE))
           foreach (
$dir as $file)
              
$arr[] = preg_replace("#(?:.+\/{1})*([^\.]+)\.(.+)#i", '$1', $file);
   }
   else
   {
      
# PHP 4.2.x code
      
$dir = php4_scandir($dir); // See code snippet above
      
if(!$ext) $ext = '\.[a-z]+';
      
$pattern = "#([^\.|\.\.$]+)$ext#i";
       foreach (
$dir as $file)
           if (
preg_match($pattern, $file, $filename))
              
$arr[] = $filename[1];
   }
  
   return (empty(
$arr) ? false : $arr);
}

?>
Bosmans Koen
24-Jan-2006 06:14
in addition to "brodseba at brodseba dot com" from march 2005:

Perfected the script to sort files and directories
in natural alphabetic order and with files listed first.
Also added a more relative directory path approach.
And changed the javascripting for links in simple ordinary href's.

Note that the script uses scandir from the pear package
(since I'm obliged to use an older PHP version).
<?
// scandir function is for php 5.0
require_once '\pear\PHP\Compat\Function\scandir.php';
// sorting function
// based on counting of dots
function cmp($a, $b) {
if (
substr_count($a,".") ==  substr_count($b,".") ) {
if (
is_string($a) && is_string($b) ) {
return
strcasecmp($a, $b) > 0 ? 1 : -1;
}elseif (
is_int($a) && is_int($b) ) {
return
$a > $b ? 1 : -1;
}elseif (
is_int($a) && is_string($b) ) {
return
1;
}elseif (
is_string($a) && is_int($b) ) {
return -
1;
}else {
return
0;
}}
return
substr_count($a,".") <  substr_count($b,".") ? 1 : -1;
}
function
ls_recursive2($dir) {
if (
is_dir($dir)) {
$files = scandir($dir);
// needed to sort array
usort ($files, "cmp");
foreach (
$files as $file) {
$currentfile = $dir . "/" . $file;
$last_dir = "";
// calculate the identation.
$count = substr_count($currentfile, '/');
$minus_count = substr_count($_SERVER['SCRIPT_FILENAME'], '/');
$count -= ($minus_count +1);
for(
$p = 0; $p < $count; $p++) {
$last_dir .= "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
}
// output with calculated identation
// first in case of directories
// run function again for directory
if (is_dir($currentfile)) {
if (
$file != '.' && $file != '..') {
$sub_len = strlen(dirname($_SERVER['SCRIPT_FILENAME']))+1;
$java_targ = substr($currentfile, $sub_len);
$last_dir .= "&nbsp;&nbsp;<img src='folder.png'
alt='' align='middle' border='0'>&nbsp;
<a href="
.$java_targ.">".$java_targ ."</a><br>\n";
echo
$last_dir;
ls_recursive2($currentfile);
}
// if not a directory, then files in current directory
} else {
$sub_len = strlen(dirname($_SERVER['SCRIPT_FILENAME']))+1;
$java_targ = substr($currentfile, $sub_len);
$last_dir .= "<img src='file.png'
alt='' align='middle' border='0'>&nbsp;
<a href="
.$java_targ.">".$java_targ."</a><br>\n";
echo
$last_dir;
}}}}
?>
<?
$this
= dirname($_SERVER['SCRIPT_FILENAME']);
echo
$this."<br>\n";
ls_recursive2($this);
?>
**
ps: I can take a comment, even some criticism,
but do understand: I'm fairly new at this.
colabus at gmail dot com
09-Jan-2006 02:02
I made a small dir listing based on file modification date, could find alot on this myself so I hope this helps someone.

<?
   $dirView
="./blah";
  
$dirFiles=scandir($dirView);
  
  
$cwdName=array(); $cwdMod=array(); $whatWeNeed=array();
  
  
// Parallel arrays (ignore the ".", ".." and inturn hidden files
  
foreach ($dirFiles as $data)
   {
       if (!
preg_match('/^\./', $data))
       {
          
$cwdName[]=$data;
          
$cwdMod[]=filemtime($dirView."/".$data);
       }
   }
  
  
// Merge and sort
  
$mergeArray=array_combine($cwdMod, $cwdName);
  
krsort($mergeArray, SORT_NUMERIC);
  
  
// Build new array
  
foreach ($mergeArray as $key => $value)
   {
      
$whatWeNeed[]=$value;
   }
  
  
// Some maintainence
  
unset($dirFiles, $cwdName, $cwdMod, $mergeArray);

  
# Then can grab latest changed file/folder with whatWeNeed[0] and so on..
?>

Tested with error_reporting(E_ALL); and PHP5.1
carlfredrik dot bowin at gmail dot com
05-Jan-2006 10:03
I made a function that scans the directory and all it subfolders. You can also sort them with folders first and files after, in alphabetic order. It works with both PHP 4 and 5.

<?php

function rec_scandir($dir)
{
  
$files = array();
   if (
$handle = opendir($dir) ) {
       while ( (
$file = readdir($handle)) !== false ) {
           if (
$file != ".." && $file != "." ) {
               if (
is_dir($dir . "/" . $file) ) {
                  
$files[$file] = rec_scandir($dir . "/" . $file);
               }else {
                  
$files[] = $file;
               }
           }
       }
      
closedir($handle);
       return
$files;
   }
}

function
cmp($a, $b)
{
   if (
is_string($a) && is_string($b) ) {
       return
strcmp($a, $b) > 0 ? 1 : -1;
   }elseif (
is_int($a) && is_int($b) ) {
       return
$a > $b ? 1 : -1;
   }elseif (
is_int($a) && is_string($b) ) {
       return
1;
   }elseif (
is_string($a) && is_int($b) ) {
       return -
1;
   }else {
       return
0;
   }
}

function
array_ukmultisort(&$arr, $func) {
  
uksort($arr, $func);
   while ( list(
$key, $val) = each($arr) ) {
       if (
is_array($val) ) {
          
array_ukmultisort($arr[$key], $func);
       }
   }
}

$dir = rec_scandir(".");
array_ukmultisort($dir, "cmp");
echo
"<pre>";
print_r($dir);
echo
"</pre>";

?>
sk3391 at gmail dot com
07-Dec-2005 10:56
Here is a little script that i through together to count the files in my directory while excluding the "."  i hope it helps you out!

<?
$dir
= ".";
$sort = 0;
  
$dir_open = @ opendir($dir);
 
   while ((
$dir_content = readdir($dir_open)) !== false)
          
$files[] = $dir_content;
 
   if (
$sort == 1) {
      
rsort($files, SORT_STRING);
} else {
      
sort($files, SORT_STRING);
}
$a=0;
$b=10;
$file_s="";
while(
$a < $b) {
 
$c=1;
$d=5;

while(
$c < $d) {
$dot[$c.",".$a]=str_repeat(".", $c);
if(
$files[$a] == $dot[$c.",".$a]) {
unset(
$files[$a]);
} else {

}

$c++;

}

if(
$files[$a] != "") {
$brake[$a]="<br>";
} else {
$brake[$a]="";
}

$file_s.=$files[$a].$brake[$a];

$a++;

}
echo
$file_s;

echo
"<br><br><br>";

echo
count($files);
?>
Yassin Ezbakhe <yassin88 at gmail dot com>
01-Sep-2005 07:18
/**********************************************
 *
 *  PURPOSE: List files inside the specified path and its
 *  subdirectories
 *
 *  array scandir_recursive (string dir)
 *
 *  This function will return a multidimensional array
 *  that represents main folder's tree structure.
 *  Each folder has its own named array
 *
 **********************************************/

function scandir_recursive($directory)
{
   $folderContents = array();
   $directory = realpath($directory).DIRECTORY_SEPARATOR;

   foreach (scandir($directory) as $folderItem)
   {
       if ($folderItem != "." AND $folderItem != "..")
       {
           if (is_dir($directory.$folderItem.DIRECTORY_SEPARATOR))
           {
               $folderContents[$folderItem] = scandir_recursive( $directory.$folderItem."\\");
           }
           else
           {
               $folderContents[] = $folderItem;
           }
       }
   }

   return $folderContents;
}
trevi55 at gmail dot com
08-Jul-2005 08:38
For non php5-users here you are this function...
It isn't set the wrapper, but I think it's enough :P.

If no pararameter is set, the scandir() function will scan the local file directory.

Set the optional parameter "$sort" to 1 to reverse the alphabetical-sorting.

<?
function scandir($dir = './', $sort = 0)
{
  
  
$dir_open = @ opendir($dir);
  
   if (!
$dir_open)
       return
false;
      
      
   while ((
$dir_content = readdir($dir_open)) !== false)
          
$files[] = $dir_content;
  
   if (
$sort == 1)
      
rsort($files, SORT_STRING);
   else
      
sort($files, SORT_STRING);
  
   return
$files;
}
?>
progrium+php at gmail dot com
01-Jul-2005 07:54
I made this to represent a directory tree in an array that uses the file or directory names as keys and full paths as the value for files. Directories are nested arrays.

<?php
function generatePathTree($rootPath) {
  
$pathStack = array($rootPath);
  
$contentsRoot = array();
  
$contents = &$contentsRoot;
   while (
$path = array_pop($pathStack)) {
      
$contents[basename($path)] = array();
      
$contents = &$contents[basename($path)];
       foreach (
scandir($path) as $filename) {
           if (
'.' != substr($filename, 0, 1)) {
              
$newPath = $path.'/'.$filename;
               if (
is_dir($newPath)) {
                  
array_push($pathStack, $newPath);
                  
$contents[basename($newPath)] = array();
               } else {
                  
$contents[basename($filename)] = $newPath;
               }
           }
       }
   }
   return
$contentsRoot[basename($rootPath)];
}
?>

The function will return something like this:

Array
(
   [index.php] => /usr/local/www/index.php
   [js] => Array
       (
           [async.js] => /usr/local/www/js/async.js
           [dom.js] => /usr/local/www/js/dom.js
           [effects.js] => /usr/local/www/js/effects.js
           [prototype.js] => /usr/local/www/js/prototype.js
       )

   [logo.png] => /usr/local/www/logo.png
   [server.php] => /usr/local/www/server.php
   [test.js] => /usr/local/www/test.js
)
welshwizard at gmail dot com
21-May-2005 10:37
Im wanting to when php executed for the script to scan for certain file extensions in a windows mapped out folder which is set as H:\ when a user logs on.

Will the php scan locally (the linux box) or will it work client side like i want?
 

thnks

Mat
pablo dot fabregat at gmail dot com
14-May-2005 05:46
i was triyng to do something similar to the ls -R command in linux, so, using the functions from csaba , i could, so, using this simple lines, you'll get that result:

<?php

$directory
= "."; // for the actual directory
$directories = dirList($directory, 2, 0); // this calls the csaba's function dirlist, wich has type 2(files) and level 0($path and all subdirectories) as parameters. And it will return an array with all the returned paths

//so i cross all over the array doing an echo for every single item of the array
foreach ($directories as $dir){
   echo
$dir."<br>";
}

?>

and that's it, remember that you need the functions listed above from csaba to use this
Pawel Dlugosz
12-May-2005 02:18
For directory containing files like (for example) -.jpg the results of scandir are a little "weird" ;)

<?php
  
   $dir
= '/somedir';
  
$files = scandir($dir);
  
print_r($files);
?>

Array
(
   [0] => -.jpg
   [1] => .
   [2] => ..
   [3] => foo.txt
   [4] => somedir
)

Beware - sorting is in ASCII order :)
wwwebdesigner at web doott de
13-Apr-2005 03:20
using sort of scandir() that returns the content sorted by Filemodificationtime.

<?php
function scandir_by_mtime($folder) {
 
$dircontent = scandir($folder);
 
$arr = array();
  foreach(
$dircontent as $filename) {
   if (
$filename != '.' && $filename != '..') {
     if (
filemtime($folder.$filename) === false) return false;
    
$dat = date("YmdHis", filemtime($folder.$filename));
    
$arr[$dat] = $filename;
   }
  }
  if (!
ksort($arr)) return false;
  return
$arr;
}
?>

returns false if an error occured
otherwise it returns an array like this.
Array
(
   [20040813231320] => DSC00023.JPG
   [20040813231456] => DSC00024.JPG
   [20040814003728] => MOV00055.MPG
   [20040814003804] => DSC00056.JPG
   [20040814003946] => DSC00057.JPG
   [20040814004030] => DSC00058.JPG
   [20040814014516] => DSC00083.JPG
   [20050401161718] => album.txt
)
brodseba at brodseba dot com
25-Mar-2005 12:53
This function create a HTML view of a directory.  It also look for subdirectory.  I use some icon to differ from folders or files.  It's also possible to get specific icon for specific file type.

Each entrey is clickable so you can use it to populate a form field.

Have fun!

function ls_recursive2($dir)
{
  if (is_dir($dir))
  {
   $files = scandir($dir);
          
   foreach ($files as $file)
   {
     $currentfile = $dir . "/" . $file;
                  
     $last_dir = "";
     // Calculate they identation.
     $count = substr_count($currentfile, '/');
     $minus_count = substr_count($_SERVER['DOCUMENT_ROOT'], '/');
     $count -= ($minus_count + 2);
              
     for($p = 0; $p < $count; $p++)
     {
       $last_dir .= "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
     }
              
     if (is_dir($currentfile))
     {
       if ($file != '.' && $file != '..')
     {
       $last_dir .= "<img src='images/folder.gif' alt='' align='middle' width='16' height='16' border='0'>&nbsp;<a href=\"javascript:go('" . $currentfile . "')\">". substr($currentfile, strrpos($currentfile, '/')) . "</a><br>";
         echo $last_dir;
         ls_recursive2($currentfile);
       }
     }
     else
     {
       $last_dir .= "<img src='images/file.gif' alt='' align='middle' width='16' height='16' border='0'>&nbsp;<a href=\"javascript:go('" . $currentfile . "')\">". substr($currentfile, strrpos($currentfile, '/')) . "</a><br>";
       echo $last_dir;
     }
   }
  }
}
csaba at alum dot mit dot edu
05-Mar-2005 07:19
Scandir on steroids:
For when you want to filter your file list, or only want to list so many levels of subdirectories...

<?php
function dirList($path="", $types=2, $levels=1, $aFilter=array()) {
//  returns an array of the specified files/directories
//  start search in $path (defaults to current working directory)
//  return $types:  2 => files; 1 => directories; 3 => both;
//  $levels: 1 => look in the $path only; 2 => $path and all children;
//          3 => $path, children, grandchildren; 0 => $path and all subdirectories;
//          less than 0 => complement of -$levels, OR everything starting -$levels down
//                e.g. -1 => everthing except $path; -2 => all descendants except $path + children
//  Remaining argument(s) is(are) a filter array(list) of regular expressions which operate on the full path.
//    First character (before the '/' of the regExp) '-' => NOT.
//    First character (after a possible '-') 'd' => apply to directory name
//    The filters may be passed in as an array of strings or as a list of strings
//  Note that output directories are prefixed with a '*' (done in the line above the return)
  
$dS = DIRECTORY_SEPARATOR;
   if (!(
$path = realpath($path?$path:getcwd()))) return array();    // bad path
   // next line rids terminating \ on drives (works since c: == c:\ on PHP).  OK in *nix?
  
if (substr($path,-1)==$dS) $path = substr($path,0,-1);
   if (
is_null($types)) $types = 2;
   if (
is_null($levels)) $levels = 1;
   if (
is_null($aFilter)) $aFilter=array();

  
// last argument may be passed as a list or as an array
  
$aFilter = array_slice(func_get_args(),3);
   if (
$aFilter && gettype($aFilter[0])=="array") $aFilter=$aFilter[0];
  
$adFilter = array();
  
// now move directory filters to separate array:
  
foreach ($aFilter as $i=>$filter)                  // for each directory filter...
    
if (($pos=stripos(" $filter","d")) && $pos<3) {  // next line eliminates the 'd'
        
$adFilter[] = substr($filter,0,$pos-1) . substr($filter,$pos);
         unset(
$aFilter[$i]); }
  
$aFilter = array_merge($aFilter);    // reset indeces

  
$aRes = array();                    // results, $aAcc is an Accumulator
  
$aDir = array($path);    // dirs to check
  
for ($i=$levels>0?$levels++:-1;($aAcc=array())||$i--&&$aDir;$aDir=$aAcc)
     while (
$dir = array_shift($aDir))
         foreach (
scandir ($dir) as $fileOrDir)
           if (
$fileOrDir!="." && $fileOrDir!="..") {
               if (
$dirP = is_dir ($rp="$dir$dS$fileOrDir"))
                 if (
pathFilter("$rp$dS", $adFilter))
                    
$aAcc[] = $rp;
               if (
$i<$levels-1 && ($types & (2-$dirP)))
                 if (
pathFilter($rp, $aFilter))
                    
$aRes[] = ($dirP?"*":"") . $rp; }
   return
$aRes;
}
?>

example usage:
<?php
define
("_", NULL);
// this will find all non .jpg, non .Thumbs.db files under c:\Photo
$aFiles = dirList('c:\Photo', _, 0, '-/\.jpg$/i', '-/\\\\Thumbs.db$/');
$aFiles = dirList();    // find the files in the current directory
// next lines will find .jpg files in non Photo(s) subdirectories, excluding Temporary Internet Files
set_time_limit(60);        // iterating from the top level can take a while
$aFiles = dirList("c:\\", _, 0, '/\.jpg$/i', '-d/\\\\Photos?$/i', '-d/Temporary Internet/i');
?>

See my earlier entry for the definition of pathFilter(...)
Note that this function will consume a lot of time if scanning large
directory structures (which is the reason for the '[-]d/.../' filters).

Csaba Gabor from Vienna
csaba at alum dot mit dot edu
04-Mar-2005 08:52
A nice way to filter the files/directories you get back from scandir:

<?php
function pathFilter ($path, $aFilter) {
  
// returns true iff $path survives the tests from $aFilter
   // $aFilter is an array of regular expressions: [-]/regExp/modifiers
   // if there is a leading '-' it means exclude $path upon a match (a NOT test)
   // If the first expression has a leading '-', $path is in, unless it gets excluded.
   // Otherwise, $path is out, unless it gets included via the filter tests.
   // The tests are applied in succession.
   // A NOT test is applied only if $path is currently (within the tests) included
   // Other tests are applied only if $path is currently excluded.  Thus,
   // array("/a/", "-/b/", "/c/") => passes if $path has a c or if $path has an a but no b
   // array("/a/", "/c/", "-/b/") => passes if $path has an a or c, but no b
   // array("-/b/", "/a/", "/c/") => passes if $path has no b, or if $path has an a or c
  
if (!$aFilter) return true;          // automatic inclusion (pass) if no filters
  
foreach ($aFilter as $filter) break;  // we don't know how it's indexed
  
$in = $filter[0]=="-";                // initial in/exclusion based on first filter
  
foreach ($aFilter as $filter)        // walk the filters
    
if ($in==$not=($filter[0]=="-"))  //    testing only when necessary
        
$in ^= preg_match(substr($filter,$not),$path);    // flip in/exclusion upon a match
  
return $in;
}
?>

Csaba Gabor from Vienna
rich at jamsoft dot biz
09-Feb-2005 11:33
Ok, in my previous example, you need to do the SORT after you remove the "." and ".." entries from the array.  Otherwise, you cannot start using the array at 0.

Here is corrected code:

<?php

function scandir($dir, $no_dots=FALSE) {

  
$files = array();
  
$dh  = @opendir($dir);
   if (
$dh!=FALSE) {
       while (
false !== ($filename = readdir($dh))) {
          
$files[] = $filename;
       }

       if (
$no_dots) {
           while((
$ix = array_search('.',$files)) > -1)
                   unset(
$files[$ix]);
           while((
$ix = array_search('..',$files)) > -1)
                   unset(
$files[$ix]);
       }

      
sort($files);

   }
   return
$files;
}

?>
virtual at NOSPAM dot lapinbleu dot ch
09-Feb-2005 09:58
Since I needed to scan dirs and subdirs and wanted to have files and dirs not in the same var without having to explode it, I did this little function:

<?php

function scan_Dir($directory=NULL)
{
$temp = "";
if (
$directory==NULL)
{
      
$directory = getcwd();
}
$handle = opendir($directory);
while (
false !== ($filename = readdir($handle)))
{
       if ((
$filename!=".") AND ($filename!=".."))
       {
               if (
is_dir($directory."/".$filename))
               {
                      
$old_directory = $directory;
                      
$directory .= "/".$filename;
                      
$temp = scan_Dir($directory);

                      
$cpt = 0;
                       while (
$cpt<count($temp["filename"]))
                       {
                              
$arrfiles["path"][]      = $directory."/".$temp["filename"][$cpt];
                              
$arrfiles["directory"][] = $directory;
                              
$arrfiles["filename"][]  = $temp["filename"][$cpt];
                              
$cpt++;
                       }
                      
$directory = $old_directory;
               }
               else
               {
                      
$arrfiles["path"][]      = $directory."/".$filename;
                      
$arrfiles["directory"][] = $directory;
                      
$arrfiles["filename"][]  = $filename;
               }
       }
}
return
$arrfiles;
}
?>

This one seems to work properly and use multidimensional array.

To show your files, just use:
<?php

$dir2scan
= "admin";
$yourvar = scan_Dir($dir2scan);

echo
$yourvar["path"][0]."<br>"; //Complete path of the file with key 0 (dir + filename)

echo $yourvar["directory"][0]."<br>"; //Directory of the file with key 0

echo $yourvar["filename"][0]."<br>"; //Filename of the file with key 0

?>

Note that the parameter of the function is not necessary. If you don't give any, it will scan from the returned value of getcwd() function.
skatecrazy1 at digibase dot ca
25-Nov-2004 02:25
Scandir can be used to make directories of files not unlike apache's indexes, but CSS enabled and fully customizable:

<?
//in this example, we'll say the directory is "images"
$list = scandir("images");
$i = 0;
$num = count($list);
while(
$i < $num){
print
"<a href=\"images/$list[$i]\">$list[$i]</a><br />";
$i++;
}
?>

That will print all the files in the "images" directory linked to the files.
Stan P. van de Burgt
27-Oct-2004 12:05
scandir() with regexp matching on file name and sorting options based on stat().

function myscandir($dir, $exp, $how='name', $desc=0)
{
   $r = array();
   $dh = @opendir($dir);
   if ($dh) {
       while (($fname = readdir($dh)) !== false) {
           if (preg_match($exp, $fname)) {
               $stat = stat("$dir/$fname");
               $r[$fname] = ($how == 'name')? $fname: $stat[$how];
           }
       }
       closedir($dh);
       if ($desc) {
           arsort($r);
       }
       else {
           asort($r);
       }
   }
   return(array_keys($r));
}

$r = myscandir('./book/', '/^article[0-9]{4}\.txt$/i', 'ctime', 1);
print_r($r);

files can be sorted on name and stat() attributes, ascending and descending:

name    file name
dev    device number
ino    inode number
mode    inode protection mode
nlink  number of links
uid    userid of owner
gid    groupid of owner
rdev    device type, if inode device *
size    size in bytes
atime  time of last access (Unix timestamp)
mtime  time of last modification (Unix timestamp)
ctime  time of last inode change (Unix timestamp)
blksize blocksize of filesystem IO *
blocks  number of blocks allocated
aidan at php dot net
21-May-2004 10:14
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat