class Dir
{
/**
* 扫描目录下所有文件,
* @var array
*/
protected static $files = [];
public static $ret = [];
/**
* 扫描目录路径
* @param $path string 带扫描的路径
* @param array $options 要附加的选项,后面可以根据自己需求扩展
* @return array
* @author: Vencenty
* @time: 2019/6/28 10:57
*/
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
* @time: 2019/6/27 17:57
*/
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
可以根据自己的需要进行扩展,
$r = Dir::scan($path, [
'callback' => function ($file) {
return filemtime($file) > strtotime('-1 day') ? $file : null; // 查找一天内修改过的文件
},
'filterExt' => ['php'] // 过滤所有PHP文件
]);
callback
回调函数可以用来实现文件过滤的功能,文件类型查找等,具体场景具体分析
options
参数相当于是扩展了函数配置项, 新的配置项会覆盖默认配置,相较于一个函数
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)
这个函数也很简单,就是带了一个强制覆盖和非强制覆盖的选项,自己实现了一下,也分享一下吧
就先这样~