XXVIII. Directory 目录函数

需求

要编译本扩展模块不需要外部库文件。

安装

本函数库作为 PHP 内核的一部分,不用安装就能使用。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

预定义常量

以下常量由本扩展模块定义,因此只有在本扩展模块被编译到 PHP 中,或者在运行时被动态加载后才有效。

DIRECTORY_SEPARATOR (string)

PATH_SEPARATOR (string)

注: PATH_SEPARATOR 是在 PHP 4.3.0-RC2 中引入。

参见

相关函数例如 dirname()is_dir()mkdir()rmdir(),见文件系统函数一章。

目录
chdir -- 改变目录
chroot -- 改变根目录
dir -- directory 类
closedir -- 关闭目录句柄
getcwd -- 取得当前工作目录
opendir -- 打开目录句柄
readdir -- 从目录句柄中读取条目
rewinddir -- 倒回目录句柄
scandir -- 列出指定路径中的文件和目录

add a note add a note User Contributed Notes
dkflbk at nm dot ru
15-Sep-2006 07:29
I wrote a simple backup script which puts all files in his folder (and all of the sub-folders) in one TAR archive...
(It's classic TAR format not USTAR, so filename and path to it can't be longer then 99 chars)
<?php
/***********************************************************
 *  Title:  Classic-TAR based backup script v0.0.1-dev
  **********************************************************/

Class Tar_by_Vladson {
   var
$tar_file;
   var
$fp;
   function
Tar_by_Vladson($tar_file='backup.tar') {
      
$this->tar_file = $tar_file;
      
$this->fp = fopen($this->tar_file, "wb");
      
$tree = $this->build_tree();
      
$this->process_tree($tree);
      
fputs($this->fp, pack("a512", ""));
      
fclose($this->fp);
   }
   function
build_tree($dir='.'){
      
$handle = opendir($dir);
       while(
false !== ($readdir = readdir($handle))){
           if(
$readdir != '.' && $readdir != '..'){
              
$path = $dir.'/'.$readdir;
               if (
is_file($path)) {
                  
$output[] = substr($path, 2, strlen($path));
               } elseif (
is_dir($path)) {
                  
$output[] = substr($path, 2, strlen($path)).'/';
                  
$output = array_merge($output, $this->build_tree($path));
               }
           }
       }
      
closedir($handle);
       return
$output;
   }
   function
process_tree($tree) {
       foreach(
$tree as $pathfile ) {
           if (
substr($pathfile, -1, 1) == '/') {
              
fputs($this->fp, $this->build_header($pathfile));
           } elseif (
$pathfile != $this->tar_file) {
              
$filesize = filesize($pathfile);
              
$block_len = 512*ceil($filesize/512)-$filesize;
              
fputs($this->fp, $this->build_header($pathfile));
              
fputs($this->fp, file_get_contents($pathfile));
              
fputs($this->fp, pack("a".$block_len, ""));
           }
       }
       return
true;
   }
   function
build_header($pathfile) {
       if (
strlen($pathfile) > 99 ) die('Error');
      
$info = stat($pathfile);
       if (
is_dir($pathfile) ) $info[7] = 0;
      
$header = pack("a100a8a8a8a12A12a8a1a100a255",
          
$pathfile,
          
sprintf("%6s ", decoct($info[2])),
          
sprintf("%6s ", decoct($info[4])),
          
sprintf("%6s ", decoct($info[5])),
          
sprintf("%11s ",decoct($info[7])),
          
sprintf("%11s", decoct($info[9])),
          
sprintf("%8s", " "),
           (
is_dir($pathfile) ? "5" : "0"),
          
"",
          
""
          
);
      
clearstatcache();
      
$checksum = 0;
       for (
$i=0; $i<512; $i++) {
          
$checksum += ord(substr($header,$i,1));
       }
      
$checksum_data = pack(
          
"a8", sprintf("%6s ", decoct($checksum))
           );
       for (
$i=0, $j=148; $i<7; $i++, $j++)
          
$header[$j] = $checksum_data[$i];
       return
$header;
   }
}

header('Content-type: text/plain');
$start_time = array_sum(explode(chr(32), microtime()));
$tar = & new Tar_by_Vladson();
$finish_time = array_sum(explode(chr(32), microtime()));
printf("The time taken: %f seconds", ($finish_time - $start_time));
?>
engin bzzzt biz
02-Feb-2006 04:07
To join directory and file names in a cross-platform manner you can use the following function.

function join_path()
{
       $num_args = func_num_args();
       $args = func_get_args();
       $path = $args[0];
      
       if( $num_args > 1 )
       {
           for ($i = 1; $i < $num_args; $i++)
           {
               $path .= DIRECTORY_SEPARATOR.$args[$i];
           }
       }
      
       return $path;
}

It should do the following:
$src = join_path( '/foo', 'bar', 'john.jpg' );
echo $src; // On *nix -> /foo/bar/john.jpg

$src = join_path( 'C:\www', 'domain.com', 'foo.jpg' );
echo $src; // On win32 -> C:\\www\\domain.com\\foo.jpg
msh at onliners dot dk
30-Jan-2006 07:49
I would like to present these two simple functions for generating a complete directory listing - as I feel the other examples are to restrictive in terms of usage.

function dirTree($dir) {
   $d = dir($dir);
   while (false !== ($entry = $d->read())) {
       if($entry != '.' && $entry != '..' && is_dir($dir.$entry))
           $arDir[$entry] = dirTree($dir.$entry.'/');
   }
   $d->close();
   return $arDir;
}

function printTree($array, $level=0) {
   foreach($array as $key => $value) {
       echo "<div class='dir' style='width: ".($level*20)."px;'>&nbsp;</div>".$key."<br/>\n";
       if(is_array($value))
           printTree($value, $level+1);
   }
}

Usage is as simple as this:
$dir = "<any directory you like>";
$arDirTree = dirTree($dir);
printTree($arDirTree);

It is easy to add files to the tree also - so enjoy.
Nicolas Merlet - admin(at)merletn.org
22-Jan-2006 11:34
Here is a very similar function to *scandir*, if you are still using PHP4...

This recursive function will return an indexed array containing all directories or files or both (depending on parameters). You can specify the depth you want, as explained below.

<?php

// $path : path to browse
// $maxdepth : how deep to browse (-1=unlimited)
// $mode : "FULL"|"DIRS"|"FILES"
// $d : must not be defined
 
function searchdir ( $path , $maxdepth = -1 , $mode = "FULL" , $d = 0 )
{
   if (
substr ( $path , strlen ( $path ) - 1 ) != '/' ) { $path .= '/' ; }     
  
$dirlist = array () ;
   if (
$mode != "FILES" ) { $dirlist[] = $path ; }
   if (
$handle = opendir ( $path ) )
   {
       while (
false !== ( $file = readdir ( $handle ) ) )
       {
           if (
$file != '.' && $file != '..' )
           {
              
$file = $path . $file ;
               if ( !
is_dir ( $file ) ) { if ( $mode != "DIRS" ) { $dirlist[] = $file ; } }
               elseif (
$d >=0 && ($d < $maxdepth || $maxdepth < 0) )
               {
                  
$result = searchdir ( $file . '/' , $maxdepth , $mode , $d + 1 ) ;
                  
$dirlist = array_merge ( $dirlist , $result ) ;
               }
       }
       }
      
closedir ( $handle ) ;
   }
   if (
$d == 0 ) { natcasesort ( $dirlist ) ; }
   return (
$dirlist ) ;
}

?>