PHP遍歷目錄下全部文件以及文件夾複製功能

<?php
class Dir
{
    /**
     * 掃描目錄下全部文件,
     * @var array
     */
    protected static $files = [];

    public static $ret = [];

    /**
     * 掃描目錄路徑
     * @param $path string 帶掃描的路徑
     * @param array $options 要附加的選項,後面能夠根據本身需求擴展
     * @return array
     * @author: Vencenty
     */
    static function scan($path, $options = [])
    {
        $options = array_merge([
            'callback'  => null, // 對查找到的文件進行操做
            'filterExt' => [], // 要過濾的文件後綴
        ], $options);

        $scanQueue = [$path];

        while (count($scanQueue) != 0) {
            $rootPath = array_pop($scanQueue);

            // 過濾['.', '..']目錄
            $paths = array_filter(scandir($rootPath), function ($path) {
                return !in_array($path, ['.', '..']);
            });

            foreach ($paths as $path) {
                // 拼接完整路徑
                $fullPath = $rootPath . DIRECTORY_SEPARATOR . $path;
                // 若是是目錄的話,合併到掃描隊列中繼續進行掃描
                if (is_dir($fullPath)) {
                    array_unshift($scanQueue, $fullPath);
                    continue;
                }

                // 若是不是空,進行過濾
                if (!empty($options['filterExt'])) {
                    $pathInfo = pathinfo($fullPath);
                    $ext = $pathInfo['extension'] ?? null;
                    if (in_array($ext, $options['filterExt'])) {
                        continue;
                    }
                }

                if ($options['callback'] instanceof Closure) {
                    // 通過callback處理以後爲空的數據不做處理
                    $fullPath = $options['callback']($fullPath);
                    // 返回的只要不是字符串路徑,不做處理
                    if (!is_string($fullPath)) {
                        continue;
                    }
                }

                array_push(static::$files, $fullPath);
            }
        }

        return static::$files;
    }

    /**
     * 目錄拷貝,返回被拷貝的文件數,
     * @param $source string 源文件,填寫絕對路徑
     * @param $dest string 目標路徑,填寫絕對路徑
     * @param $force bool 開啓會每次強制覆蓋原文件,false不進行覆蓋,存在文件不作處理
     * @return int 拷貝的文件數
     * @author: Vencenty
     */
    static function copy($source, $dest, $force = true)
    {
        static $counter = 0;
        $paths = array_filter(scandir($source), function ($file) {
            return !in_array($file, ['.', '..']);
        });

        foreach ($paths as $path) {
            // 要拷貝的源文件的完整路徑
            $sourceFullPath = $source . DIRECTORY_SEPARATOR . $path;
            // 要拷貝到的文件的路徑
            $destFullPath = $dest . DIRECTORY_SEPARATOR . $path;

            // 拷貝的目標地址若是是否是文件夾,那麼說明文件夾不存在,那麼首先建立文件夾
            if (is_dir($sourceFullPath)) {
                if (!is_dir($destFullPath)) {
                    mkdir($destFullPath);
                    chmod($destFullPath, 0755);
                }
                // 遞歸copy
                static::copy($sourceFullPath, $destFullPath, $force);
                continue;
            }

            // 不開啓強制覆蓋的話若是已經存在文件了那麼直接跳過,不進行處理
            if (!$force && file_exists($destFullPath)) {
                continue;
            }

            // 每次copy成功文件計數器+1
            if (copy($sourceFullPath, $destFullPath)) {
                $counter++;
            }
        }

        return $counter;
    }
}
$path = realpath('../');
$r = Dir::scan($path, [
    'callback' => function ($file) {
        return filemtime($file) > strtotime('-1 day') ? $file : null; // 查找修改過的文件
    },
    'filterExt' => []
]);
//print_r($r);

$r = Dir::copy('C:\phpStudy\PHPTutorial\WWW\php\.idea', 'C:\phpStudy\PHPTutorial\WWW\php', true);
print_r($r);

項目中須要使用這兩個功能,因此就寫了這兩個方法,其中scan方法的第二個參數options能夠根據本身的須要進行擴展,php

$r = Dir::scan($path, [
    'callback' => function ($file) {
        return filemtime($file) > strtotime('-1 day') ? $file : null; // 查找一天內修改過的文件
    },
    'filterExt' => ['php'] // 過濾全部PHP文件
]);

callback回調函數能夠用來實現文件過濾的功能,文件類型查找等,具體場景具體分析
options參數至關因而擴展了函數配置項, 新的配置項會覆蓋默認配置,相較於一個函數ide

static function scan($path, $callback, $filterExt) {}

我更喜歡下面這種寫法,更靈活一些函數

static function scan($path, $options) 
{
    $options = array_merge([
        'callback' => null,
        'filterExt' => [],
        'otherOptions' => null 
    ], $options);    
}

Dir::copy($source, $dest, $force = true) 這個函數也很簡單,就是帶了一個強制覆蓋和非強制覆蓋的選項,本身實現了一下,簡單記錄一下idea

相關文章
相關標籤/搜索