PHP List Directory structure and exclude some directories

前端 未结 8 674
南笙
南笙 2020-12-18 05:44

I have this PHP Code:

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

for         


        
相关标签:
8条回答
  • 2020-12-18 05:57

    I would keep it simpler, with some basic php functions, easy to read (no thirty part, no delegations to other objects), and this few lines.

    First, you create a function,that receives the dir you want to explore, and an optional array or excluded filenames

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

    Now, you just have to call the function

    $files= getFiles($rootpath) ;
    

    or if you want to exclude some files if they exist, you can call

    $files= getFiles($rootpath, array(".htaccess","otherfile", "etc")) ;
    
    0 讨论(0)
  • 2020-12-18 06:12

    I feel that some of the other answers are good, but more verbose than they need to be. Here is a some simple code. My example only filters the .git directory, but you can easily expand it to other items:

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

    0 讨论(0)
  • 2020-12-18 06:14

    My suggestion is to try using Symfony's finder library as it makes alot of this much easier and is easily installed via composer here are the docs

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

    and here is a simple example of something similar to what i think you're asking

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

    That example will return all directories without transversing into them to change that change or remove the depth.

    To get all files in that directory do something similar to this

    <?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>';
        }
    }
    
    0 讨论(0)
  • 2020-12-18 06:15

    If I correct guess you then you just want add to base only path for files, not for directory.

    Just use for check function is_file in your foreach

    For example

    foreach ($fileinfos as $pathname => $fileinfo)
    {
    
        if (!is_file($pathname)) 
        {
             continue;// next step
        }
        $pathname2 = substr($pathname,2);
        ...
    }
    
    0 讨论(0)
  • 2020-12-18 06:17

    In essence, my answer is not much different from Thomas' answer. However, he does not get a few things correct:

    • The semantics correct for the RecursiveCallbackFilterIterator require you to return true to recurse into subdirectories.
    • He doesn't skip the . and .. directories inside each sub-directory
    • His in_array check doesn't quite do what he expects

    So, I wrote this answer instead. This will work correctly, assuming I understand what you want:

    Edit: He has since fixed 2 of those three issues; the third may not be an issue because of the way he wrote his conditional check but I am not quite sure.

    <?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
    }
    
    0 讨论(0)
  • 2020-12-18 06:19

    You can use RecursiveFilterIterator to filter dirs and in fooreach loop you have only accepted dirs.

    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 讨论(0)
提交回复
热议问题