2013-11-28 485 views
4

我有這樣的PHP代碼:PHP目錄的目錄結構和排除了某些目錄

$rootpath = '../admin/'; 
$inner = new RecursiveDirectoryIterator($rootpath); 
$fileinfos = new RecursiveIteratorIterator($inner); 

foreach ($fileinfos as $pathname => $fileinfo) 
{ 
    $pathname2 = substr($pathname,2); 
    $sql = "SELECT * from admin_permissions where page_name = '$pathname2'"; 
    $rs = mysql_query($sql,$conn); 
    if (mysql_num_rows($rs) == 0) 
    { 
     if (!$fileinfo->isFile()) continue; 
     $sql2 = "INSERT into admin_permissions (page_name) values ('$pathname2')"; 
     $rs2 = mysql_query($sql2,$conn); 
     echo "$pathname<br>"; 
    } 
} 

這顯示的是我的目錄結構和插入的目錄和文件名到數據庫中(除去前兩個字符..)。

由於RecursiveDirectoryIterator遍歷所有目錄中的所有文件,我怎樣才能排除整個目錄,包括其中的所有文件?

+0

'if($ pathname == $ dontWant)continue;'或者使用'FilterIterator'。還有很多其他的可能性。 – deceze

+0

我想排除目錄中的所有文件,而不僅僅是選擇文件 – charlie

+1

那麼,這與您在問題中所說的相反。但是請檢查'$ fileinfo-> isDir()'/'isFile()',而不是你已經在做的事情。我不確定這裏真正的問題是什麼。 – deceze

回答

9

我建議使用RecursiveCallbackFilterIterator。

$directory = '../admin/'; 
$filter = array('.git'); 

$fileinfos = new RecursiveIteratorIterator(
    new RecursiveCallbackFilterIterator(
    new RecursiveDirectoryIterator(
     $directory, 
     RecursiveDirectoryIterator::SKIP_DOTS 
    ), 
    function ($fileInfo, $key, $iterator) use ($filter) { 
     return $fileInfo->isFile() || !in_array($fileInfo->getBaseName(), $filter); 
    } 
) 
); 

foreach($fileinfos as $pathname => $fileinfo) { 
    //... 
} 
+0

我可能會擴展'RecursiveFilterIterator'並重寫'accept()'方法而不是回調變量。個人喜好我猜。無論哪種方式,我認爲使用Spl迭代器是最正確的方式,所以+1。 – Leigh

+0

我剛剛對此表示讚賞,但您的答案實際上並非如此,因此有幾個原因。 –

+0

我測試了一個積極的檢查(較少的結果),並忘記添加!背部。函數的返回值是一個布爾值。 「。」,「..」條目的好處。 – ThW

1

我的建議是使用的Symfony的取景器庫嘗試,因爲它使很多的這個更容易,很容易通過作曲家安裝這裏的文檔

http://symfony.com/doc/current/components/finder.html

,這裏是一個簡單的例子類似於我認爲你所要求的東西

<?php 
use Symfony\Component\Finder\Finder; 

/** 
* @author Clark Tomlinson <[email protected]> 
* @since 12/6/13, 12:52 PM 
* @link http://www.clarkt.com 
* @copyright Clark Tomlinson © 2013 
* 
*/ 

require_once('vendor/autoload.php'); 

$finder = new Finder(); 
$directories = $finder->directories() 
         ->in(__DIR__) 
         ->ignoreDotFiles(true) 
         ->exclude(array('one', 'two', 'three', 'four')) 
         ->depth(0); 

foreach ($directories as $dir) { 
    echo '<pre>'; 
    print_r($dir->getRealPath()); 
    echo '</pre>'; 
} 

該示例將返回所有目錄而不橫向到它們cha更改或刪除深度。

要獲得該目錄中的所有文件做類似這樣的

<?php 
use Symfony\Component\Finder\Finder; 

/** 
* @author Clark Tomlinson <[email protected]> 
* @since 12/6/13, 12:52 PM 
* @link http://www.clarkt.com 
* @copyright Clark Tomlinson © 2013 
* 
*/ 

require_once('vendor/autoload.php'); 

$finder = new Finder(); 
$directories = $finder->directories() 
         ->in(__DIR__) 
         ->ignoreDotFiles(true) 
         ->exclude(array('one', 'two', 'three', 'four')) 
         ->depth(0); 

foreach ($directories as $dir) { 
    $files = $finder->files() 
        ->ignoreDotFiles(true) 
        ->in($dir->getRealPath()); 

    foreach ($files as $file) { 
     echo '<pre>'; 
     print_r($file); 
     echo '</pre>'; 
    } 
} 
0

東西,我會保持它的簡單,有一些基本的PHP函數,容易閱讀(無30部分,沒有代表團到其他對象),和這幾行。

首先,創建一個功能,即接收你想探索, dir和一個可選的陣列或排除的文件名

function getFiles($dir , $exclude=array()){ 
    $acceptedfiles=array(); 
    $handle=opendir($dir); 
    //reads the filenames, one by one 
    while ($file = readdir($handle)) { 
     if ($file!="." && $file!=".." && is_file($file) && !in_array($file, $exclude)) 
     $acceptedfiles[]=$file; 
    } 
    closedir($handle); 
    return $acceptedfiles; 
} 

現在,你只需要調用函數

$files= getFiles($rootpath) ; 

或者如果你想排除一些文件,如果它們存在,你可以撥打

$files= getFiles($rootpath, array(".htaccess","otherfile", "etc")) ; 
0

我會做這樣的:

$excludes = array(
    'files' => array('file1.ext','file2.ext','fileN.ext'), 
    'dirs' => array('dir1','dir2','dirN') 
); 

foreach ($directories as $current_dir) { 
    if (!in_array($current_dir,$excludes['dirs'])) { 
     // directory method 
     foreach ($files as $current_file) { 
      if (!in_array($current_file,$excludes['files'])) { 
       // files method 
      } 
     } 
    } 
} 
+0

這不是遞歸的工作,但否則我喜歡簡單。 –

0

您可以使用RecursiveFilterIterator過濾迪爾斯和fooreach循環中,您只接受迪爾斯。

class MyDirFilter extends RecursiveFilterIterator { 
    public function accept() { 

     $excludePath = array('exclude_dir1', 'exclude_dir2'); 
     foreach($excludePath as $exPath){ 
      if(strpos($this->current()->getPath(), $exPath) !== false){ 
       return false; 
      } 
     } 
     return true; 

    } 
} 

$rootpath = '../admin/'; 
$dirIterator = new RecursiveDirectoryIterator($rootpath); 
$filter = new MyDirFilter($dirIterator); 
$fileinfos = new RecursiveIteratorIterator($filter); 

foreach($fileinfos as $pathname => $fileinfo) 
{ 
    // only accepted dirs in loop 
} 
0

如果我正確猜測你,那麼你只是想添加到僅基於文件的路徑,而不是目錄。

在你的foreach

只是用於檢查功能is_file例如

foreach ($fileinfos as $pathname => $fileinfo) 
{ 

    if (!is_file($pathname)) 
    { 
     continue;// next step 
    } 
    $pathname2 = substr($pathname,2); 
    ... 
} 
15

從本質上說,我的答案是不Thomas的回答非常不同。然而,他沒有得到幾件事情糾正:

  • 正確的RecursiveCallbackFilterIterator語義要求您返回true遞歸到子目錄。
  • 他不會跳過每個子目錄
  • in_array檢查並不完全這樣做,他預計什麼

所以,我寫這個答案,而不是內部的...目錄。這將工作正常,假設我明白你想要什麼:

編輯:他已經修復了這三個問題中的2個;第三個可能不是問題,因爲他寫了他的有條件支票,但我不太確定。

<?php 

$directory = '../admin'; 

// Will exclude everything under these directories 
$exclude = array('.git', 'otherDirToExclude'); 

/** 
* @param SplFileInfo $file 
* @param mixed $key 
* @param RecursiveCallbackFilterIterator $iterator 
* @return bool True if you need to recurse or if the item is acceptable 
*/ 
$filter = function ($file, $key, $iterator) use ($exclude) { 
    if ($iterator->hasChildren() && !in_array($file->getFilename(), $exclude)) { 
     return true; 
    } 
    return $file->isFile(); 
}; 

$innerIterator = new RecursiveDirectoryIterator(
    $directory, 
    RecursiveDirectoryIterator::SKIP_DOTS 
); 
$iterator = new RecursiveIteratorIterator(
    new RecursiveCallbackFilterIterator($innerIterator, $filter) 
); 

foreach ($iterator as $pathname => $fileInfo) { 
    // do your insertion here 
}