2010-03-27 167 views
2

我有一組深度至少爲4或5級的文件夾。我正在尋找通過目錄樹進行遞歸,並迭代每個文件。我已經將代碼下載到第一組子目錄中,但沒有更深入,我不知道爲什麼。有任何想法嗎?通過PHP中的目錄樹遞歸

$count = 0; 
$dir = "/Applications/MAMP/htdocs/site.com"; 
function recurseDirs($main, $count){ 
    $dir = "/Applications/MAMP/htdocs/site.com"; 
    $dirHandle = opendir($main); 
    echo "here"; 
    while($file = readdir($dirHandle)){ 
     if(is_dir($file) && $file != '.' && $file != '..'){ 
      echo "isdir"; 
      recurseDirs($file); 
     } 
     else{ 
      $count++; 
      echo "$count: filename: $file in $dir/$main \n<br />"; 
     } 
    } 
} 
recurseDirs($dir, $count); 

回答

0

對is_dir和recurseDirs的調用不完全正確。您的計數也無法正常工作。這適用於我:

$dir = "/usr/"; 
function recurseDirs($main, $count=0){ 
    $dirHandle = opendir($main); 
    while($file = readdir($dirHandle)){ 
     if(is_dir($main.$file."/") && $file != '.' && $file != '..'){ 
      echo "Directory {$file}: <br />"; 
      $count = recurseDirs($main.$file."/",$count); // Correct call and fixed counting 
     } 
     else{ 
      $count++; 
      echo "$count: filename: $file in $main \n<br />"; 
     } 
    } 
    return $count; 
} 
$number_of_files = recurseDirs($dir); 

請注意對上述函數的更改調用和函數的新返回值。

17

查看新的RecursiveDirectoryIterator

由於您無法訂購搜索結果和其他內容,因此它還很不完善,但只是簡單地獲取文件列表就沒有問題。

有簡單的例子,讓你在手冊中開始像這樣的:

<?php 

$path = realpath('/etc'); 

$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), 
RecursiveIteratorIterator::SELF_FIRST); 

foreach($objects as $name => $object){ 
    echo "$name\n"; 
} 

?> 
+0

只是一個句話:一個迭代器做什麼它的名字所暗示的。它遍歷一個可迭代的源代碼。這與迭代數組沒有區別。如果你想要結果排序,那麼你必須在foreach循環中執行此操作,或者編寫/使用函數來爲您執行此操作。 – Gordon 2010-03-27 11:03:32

+1

@戈登真。但是,能夠將結果排序和/或直接過濾是我期望從遞歸目錄迭代器中獲得的一個特性 - 但我知道這可能不在SPL的spririt中,但仍然是這樣。實際上,還需要提出幾十行代碼(網上有數百個代碼片段,質量各不相同),以執行相當標準的任務,其中其他語言提供現成的功能。有時候讓我有點生氣。 – 2010-03-27 11:08:00

+0

@Pekka因爲現在一切都可以是一個Iterable,所以不可能想出一個通用的排序方式。它應該如何知道我希望我的Person對象按$ firstName排序,但是我的Files by MTime?你有*腳本。如果您想通過泛型表達式查詢對象,請查看PHPLinq。 – Gordon 2010-03-27 11:14:21

2

有呼叫錯誤

recurseDirs($file); 

is_dir($file) 

你必須給出完整的路徑:

recurseDirs($main . '/' .$file, $count); 

is_dir($main . '/' .$file) 

然而,像其他anwerers,我建議使用RecursiveDirectoryIteretor

0

所以是的:今天我正在懶惰和谷歌搜索曲奇解決方案的遞歸目錄列表,並遇到了這個。最後,我寫了自己的功能(至於爲什麼我花時間去Google這方面卻超出了我的想象 - 我似乎總覺得有必要重新發明輪子,因爲沒有合適的理由),我覺得我傾向於分享我的看法在這。

雖然有意見反對使用RecursiveDirectoryIterator,但我只是簡單地發表一個簡單的遞歸目錄函數,並避免在RecursiveDirectoryIterator中聲明的策略。

這就是:

function recursiveDirectoryList($root) 
{ 

    /* 
    * this next conditional isn't required for the code to function, but I 
    * did not want double directory separators in the resulting array values 
    * if a trailing directory separator was provided in the root path; 
    * this seemed an efficient manner to remedy said problem easily... 
    */ 
    if(substr($root, -1) === DIRECTORY_SEPARATOR) 
    { 
     $root = substr($root, 0, strlen($root) - 1); 
    } 

    if(! is_dir($root)) return array(); 

    $files = array(); 
    $dir_handle = opendir($root); 

    while(($entry = readdir($dir_handle)) !== false) 
    { 

     if($entry === '.' || $entry === '..') continue; 

     if(is_dir($root . DIRECTORY_SEPARATOR . $entry)) 
     { 
      $sub_files = recursiveDirectoryList( 
       $root . 
       DIRECTORY_SEPARATOR . 
       $entry . 
       DIRECTORY_SEPARATOR 
      ); 
      $files = array_merge($files, $sub_files); 
     } 
     else 
     { 
      $files[] = $root . DIRECTORY_SEPARATOR . $entry; 
     } 
    } 

    return (array) $files; 

} 

使用此功能,答案以獲得文件計數很簡單:

$dirpath = '/your/directory/path/goes/here/'; 

$files = recursiveDirectoryList($dirpath); 

$number_of_files = sizeof($files); 

但是,如果你不想數組的開銷的相應文件路徑 - 或者根本就不需要它 - 不需要按照推薦的方式將遞歸計數傳遞給遞歸函數。

人們可以簡單的修改我的原始功能進行計數這樣:

function recursiveDirectoryListC($root) 
{ 

    $count = 0; 

    if(! is_dir($root)) return (int) $count; 

    $dir_handle = opendir($root); 

    while(($entry = readdir($dir_handle)) !== false) 
    { 

     if($entry === '.' || $entry === '..') continue; 

     if(is_dir($root . DIRECTORY_SEPARATOR . $entry)) 
     { 
      $count += recursiveDirectoryListC(
       $root . 
       DIRECTORY_SEPARATOR . 
       $entry . 
       DIRECTORY_SEPARATOR 
      ); 
     } 
     else 
     { 
      $count++; 
     } 

    } 

    return (int) $count; 

} 

在這兩個功能的執行opendir()函數應該被包裹在有條件的情況下,該目錄是不可讀或發生其他錯誤。請務必使正確的事:

if(($dir_handle = opendir($dir)) !== false) 
{ 
    /* perform directory read logic */ 
} 
else 
{ 
    /* do something on failure */ 
} 

希望這可以幫助別人......