繁体   English   中英

PHP 列出目录结构并排除部分目录

[英]PHP List Directory structure and exclude some directories

我有这个 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>";
    }
}

即显示我的目录结构并将目录和文件名插入数据库(删除前 2 个字符.. )。

由于RecursiveDirectoryIterator遍历所有目录中的所有文件,如何排除整个目录,包括其中的所有文件?

本质上,我的回答与Thomas的回答没有太大区别。 但是,他没有正确理解以下几点:

  • RecursiveCallbackFilterIterator正确语义要求您返回true以递归到子目录中。
  • 他没有跳过. ..每个子目录中的目录
  • 他的in_array检查并不完全符合他的预期

所以,我写了这个答案。 这将正常工作,假设我明白你想要什么:

编辑:他已经修复了这三个问题中的两个; 第三个可能不是问题,因为他写条件支票的方式,但我不太确定。

<?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
}

我建议使用 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) {
  //...
}

我的建议是尝试使用 Symfony 的 finder 库,因为它使很多事情变得更容易,并且可以通过 Composer 轻松安装这里是文档

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

这是一个简单的例子,类似于我认为你在问什么

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

/**
 * @author Clark Tomlinson  <fallen013@gmail.com>
 * @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>';
}

该示例将返回所有目录,而无需遍历它们以更改该更改或删除深度。

要获取该目录中的所有文件,请执行与此类似的操作

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

/**
 * @author Clark Tomlinson  <fallen013@gmail.com>
 * @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>';
    }
}

您可以使用 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
}

我会让它更简单,有一些基本的 php 函数,易于阅读(没有三十部分,没有对其他对象的委托),还有这几行。

首先,您创建一个函数,它接收您要探索的目录,以及一个可选的数组或排除的文件名

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")) ;

我会这样做:

$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
            }
        }
    }
}

如果我猜对了你,那么你只想添加到文件的基本路径,而不是目录。

只需在 foreach 中用于检查函数is_file

例如

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

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

我觉得其他一些答案很好,但比他们需要的要冗长。 这是一些简单的代码。 我的示例仅过滤.git目录,但您可以轻松将其扩展到其他项目:

<?php

$f_filter = fn ($o_file) => $o_file->getFilename() == '.git' ? false : true;
$o_dir = new RecursiveDirectoryIterator('.');
$o_filter = new RecursiveCallbackFilterIterator($o_dir, $f_filter);
$o_iter = new RecursiveIteratorIterator($o_filter);

foreach ($o_iter as $o_file) {
   echo $o_file->getPathname(), "\n";
}

https://php.net/class.recursivecallbackfilteriterator

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM