php版相片按拍照日期归类整理源码
php版照片按拍照日期归类整理源码
- php版照片按拍照日期归类整理源码
- 以年-月为目录进行归类
- 跳过重复文件
- 视频文件、非图片文件单独归类
- 读不到日期的照片单独归类
<?php /* 2014/4/1 17:27 klggg 照片按拍照日期整理 依赖 php_exif 扩展 win下打开扩展 extension=php_exif.dll ; 注,这段必须放在 extension=php_mbstring.dll 下面*/date_default_timezone_set('PRC');//require dirname(__FILE__).'/vendor/autoload.php';$curr_dir_path = dirname(__FILE__); //要处理的照片来源路径 * 需要针对自己的情况做下修改$photo_source_path = 'K:/家庭照片';$config = array( 'fileExtension' => array( //图片的扩展名 'pic' => array('jpg','png','gif','bmp'), //视频的扩展名 'movies' => array('mov','3gp','mp4') ), 'path' => array( //所有新目录产生的根目录,* 注意修改成自己的路径 'root' => $curr_dir_path.'/pic_new_month' ));$config['path']['pic'] = $config['path']['root'].'/pic'; //照片移到哪个目录$config['path']['movies'] = $config['path']['root'].'/movies'; //视频移到哪个目录$config['path']['unkown'] = $config['path']['root'].'/unkown'; //非照片文件移到哪个目录//初始化log相关$log_path = $config['path']['root'].'/log/';if(!is_dir($log_path)) mkdir($log_path, 0755, true); $log_file = $log_path.'/'.date('Y-m-d').'.log';$log_category = 'PhotoMove';$log =null;$log_config = array('locking' => 1,'buffering' => true, 'lineFormat' =>'%1$s %2$s [%3$s] %8$s->%7$s %6$s %4$s');if(!defined('PEAR_LOG_DEBUG')){ define('PEAR_LOG_EMERG', 0); /* System is unusable */ define('PEAR_LOG_ALERT', 1); /* Immediate action required */ define('PEAR_LOG_CRIT', 2); /* Critical conditions */ define('PEAR_LOG_ERR', 3); /* Error conditions */ define('PEAR_LOG_WARNING', 4); /* Warning conditions */ define('PEAR_LOG_NOTICE', 5); /* Normal but significant */ define('PEAR_LOG_INFO', 6); /* Informational */ define('PEAR_LOG_DEBUG', 7); /* Debug-level messages */ $log = DefaultLog::singleton("file" , $log_file,$log_category , $log_config ,PEAR_LOG_DEBUG);}else{ $log = Log::singleton("file" , $log_file,$log_category , $log_config ,PEAR_LOG_DEBUG);}$PhotoMove_obj= new PhotoMove($config,$log);$PhotoMove_obj->run($photo_source_path);echo "done";class PhotoMove { private $mRootPath= './tmp'; private $logger= null; private $mConfig= Array(); public function __construct($config,$logger) { $this->mConfig = $config; $this->mRootPath = $config['path']['root']; foreach($config['path'] as $tmp_path) { if(!is_dir($tmp_path)) mkdir($tmp_path, 0755, true); } $this->logger = $logger; } /** * 运行脚本入口 * @param string $srcPath 照片来源目录 * */ public function run($srcPath) { $it = new RecursiveDirectoryIterator($srcPath); foreach (new RecursiveIteratorIterator($it, 2) as $file_path) { if ($file_path->isDir()) continue; $file_path_name = $file_path->__toString(); $this->logger->info('file_path_name: '.$file_path_name); $file_info = pathinfo($file_path_name); if('thumbs.db' == strtolower($file_info['basename'])) continue; if(!isset($file_info['extension'])) { $this->logger->notice('no extension : '.$file_path_name); $file_info['extension'] = ''; } $file_info['extension'] = strtolower($file_info['extension']); //找到图片 if(in_array($file_info['extension'],$this->mConfig['fileExtension']['pic'])) { $tmp_timestamp = $this->getDateTimeOriginal($file_path_name); //移到新目录 $new_dir = $this->mConfig['path']['pic'].'/'.date('Y-m',$tmp_timestamp); if(!is_dir($new_dir)) mkdir($new_dir, 0755, true); $tmp_new_file_path = $new_dir.'/'.$file_info['basename']; $this->move($file_path_name,$tmp_new_file_path); } else if(in_array($file_info['extension'],$this->mConfig['fileExtension']['movies'])) { $tmp_new_file_path = $this->mConfig['path']['movies'].'/'.$file_info['basename']; $this->move($file_path_name,$tmp_new_file_path); } else { //非图片文件处理 $this->logger->notice('not image file : '.$file_path_name); $tmp_new_file_path = $this->mConfig['path']['unkown'].'/'.$file_info['basename']; $this->move($file_path_name, $tmp_new_file_path); } } } /** * 取拍照日期 * @param string $filePathName 照片完整路径 * @param string $defaultDateTime 取不到拍照时间时的默认时间 * @return int 返回时间戳 * */ public function getDateTimeOriginal($filePathName,$defaultDateTime='1970:01:01 01:01:01') { $exif = exif_read_data($filePathName, 0, true); $date_time_original = $defaultDateTime; if(empty($exif['EXIF']) || empty($exif['EXIF']['DateTimeOriginal'])) { $this->logger->warning("empty DateTimeOriginal"); } else $date_time_original = $exif['EXIF']['DateTimeOriginal']; //string(19) "2011:03:13 10:23:09" $this->logger->info('DateTimeOriginal: '.$date_time_original); $tmp_timestamp = strtotime($date_time_original); return $tmp_timestamp; } /** * 移动文件 * @param string $oldFilePath 原文件完整路径 * @param string $newFilePath 目标文件完整路径 * @return bool * */ public function move($oldFilePath,$newFilePath) { //针对已存在的文件 if(file_exists($newFilePath)) { $this->logger->notice("file_exists ".$newFilePath); return false; } $result = false;// if($result == copy($oldFilePath, $newFilePath)) if($result == rename($oldFilePath, $newFilePath)) $this->logger->err("rename false, to ".$newFilePath ); else $this->logger->info('[ok] move '.$oldFilePath.' to '.$newFilePath); return $result; }}class DefaultLog { var $_formatMap = array('%{timestamp}' => '%1$s', '%{ident}' => '%2$s', '%{priority}' => '%3$s', '%{message}' => '%4$s', '%{file}' => '%5$s', '%{line}' => '%6$s', '%{function}' => '%7$s', '%{class}' => '%8$s', '%\{' => '%%{'); var $_lineFormat = '%1$s %2$s [%3$s] %4$s'; var $_timeFormat = '%b %d %H:%M:%S'; var $_eol = "\n"; var $_dirmode = 0755; private $_filename= './tmp'; var $_backtrace_depth = 0; public function __construct($name, $ident, $conf, $level='') { $this->_filename = $name; $this->_ident = $ident; if (!empty($conf['lineFormat'])) { $this->_lineFormat = str_replace(array_keys($this->_formatMap), array_values($this->_formatMap), $conf['lineFormat']); } if (!is_dir(dirname($this->_filename))) { mkdir(dirname($this->_filename, $this->_dirmode,true)); } } public static function singleton($handler, $name = '', $ident = '', $conf = array(), $level = PEAR_LOG_DEBUG) { static $instances; if (!isset($instances)) $instances = array(); $signature = serialize(array($handler, $name, $ident, $conf, $level)); if (!isset($instances[$signature])) { $instances[$signature] = new self($name, $ident, $conf, $level); } return $instances[$signature]; } function log($message, $priority = null) { /* Extract the string representation of the message. */ $message = $this->_extractMessage($message); /* Build the string containing the complete log line. */ $line = $this->_format($this->_lineFormat, strftime($this->_timeFormat), $priority, $message) . $this->_eol; error_log($line, 3,$this->_filename);echo $line; } function emerg($message) { return $this->log($message, PEAR_LOG_EMERG); } function alert($message) { return $this->log($message, PEAR_LOG_ALERT); } function crit($message) { return $this->log($message, PEAR_LOG_CRIT); } function err($message) { return $this->log($message, PEAR_LOG_ERR); } function warning($message) { return $this->log($message, PEAR_LOG_WARNING); } function notice($message) { return $this->log($message, PEAR_LOG_NOTICE); } function info($message) { return $this->log($message, PEAR_LOG_INFO); } function debug($message) { return $this->log($message, PEAR_LOG_DEBUG); } function _extractMessage($message) { /* * If we've been given an object, attempt to extract the message using * a known method. If we can't find such a method, default to the * "human-readable" version of the object. * * We also use the human-readable format for arrays. */ if (is_object($message)) { if (method_exists($message, 'getmessage')) { $message = $message->getMessage(); } else if (method_exists($message, 'tostring')) { $message = $message->toString(); } else if (method_exists($message, '__tostring')) { $message = (string)$message; } else { $message = var_export($message, true); } } else if (is_array($message)) { if (isset($message['message'])) { if (is_scalar($message['message'])) { $message = $message['message']; } else { $message = var_export($message['message'], true); } } else { $message = var_export($message, true); } } else if (is_bool($message) || $message === NULL) { $message = var_export($message, true); } /* Otherwise, we assume the message is a string. */ return $message; } function _format($format, $timestamp, $priority, $message) { /* * If the format string references any of the backtrace-driven * variables (%5 %6,%7,%8), generate the backtrace and fetch them. */ if (preg_match('/%[5678]/', $format)) { /* Plus 2 to account for our internal function calls. */ $d = $this->_backtrace_depth + 2; list($file, $line, $func, $class) = $this->_getBacktraceVars($d); } /* * Build the formatted string. We use the sprintf() function's * "argument swapping" capability to dynamically select and position * the variables which will ultimately appear in the log string. */ return sprintf($format, $timestamp, $this->_ident, $this->priorityToString($priority), $message, isset($file) ? $file : '', isset($line) ? $line : '', isset($func) ? $func : '', isset($class) ? $class : ''); } function priorityToString($priority) { $levels = array( PEAR_LOG_EMERG => 'emergency', PEAR_LOG_ALERT => 'alert', PEAR_LOG_CRIT => 'critical', PEAR_LOG_ERR => 'error', PEAR_LOG_WARNING => 'warning', PEAR_LOG_NOTICE => 'notice', PEAR_LOG_INFO => 'info', PEAR_LOG_DEBUG => 'debug' ); return $levels[$priority]; } function _getBacktraceVars($depth) { /* Start by generating a backtrace from the current call (here). */ $bt = debug_backtrace(); /* Store some handy shortcuts to our previous frames. */ $bt0 = isset($bt[$depth]) ? $bt[$depth] : null; $bt1 = isset($bt[$depth + 1]) ? $bt[$depth + 1] : null; /* * If we were ultimately invoked by the composite handler, we need to * increase our depth one additional level to compensate. */ $class = isset($bt1['class']) ? $bt1['class'] : null; if ($class !== null && strcasecmp($class, 'Log_composite') == 0) { $depth++; $bt0 = isset($bt[$depth]) ? $bt[$depth] : null; $bt1 = isset($bt[$depth + 1]) ? $bt[$depth + 1] : null; $class = isset($bt1['class']) ? $bt1['class'] : null; } /* * We're interested in the frame which invoked the log() function, so * we need to walk back some number of frames into the backtrace. The * $depth parameter tells us where to start looking. We go one step * further back to find the name of the encapsulating function from * which log() was called. */ $file = isset($bt0) ? $bt0['file'] : null; $line = isset($bt0) ? $bt0['line'] : 0; $func = isset($bt1) ? $bt1['function'] : null; /* * However, if log() was called from one of our "shortcut" functions, * we're going to need to go back an additional step. */ if (in_array($func, array('emerg', 'alert', 'crit', 'err', 'warning', 'notice', 'info', 'debug'))) { $bt2 = isset($bt[$depth + 2]) ? $bt[$depth + 2] : null; $file = is_array($bt1) ? $bt1['file'] : null; $line = is_array($bt1) ? $bt1['line'] : 0; $func = is_array($bt2) ? $bt2['function'] : null; $class = isset($bt2['class']) ? $bt2['class'] : null; } /* * If we couldn't extract a function name (perhaps because we were * executed from the "main" context), provide a default value. */ if ($func === null) { $func = '(none)'; } /* Return a 4-tuple containing (file, line, function, class). */ return array($file, $line, $func, $class); } }

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

使用Java的File.length()函数获取文件的大小文件大小是在处理文件操作时很常见的一个需求,Java提供了一个很方便的方法来获取文件的大小,即使用File类的length()方法。本文将介绍如何使用该方法来获取文件的大小,并给出相应的代码示例。首先,我们需要创建一个File对象来表示我们想要获取大小的文件。以下是创建File对象的方法:Filef

php blob转file的方法:1、创建一个php示例文件;2、通过“function blobToFile(blob) {return new File([blob], 'screenshot.png', { type: 'image/jpeg' })}”方法实现Blob转File即可。

想了解更多关于开源的内容,请访问:51CTO鸿蒙开发者社区https://ost.51cto.com运行环境DAYU200:4.0.10.16SDK:4.0.10.15IDE:4.0.600一、创建应用点击File->newFile->CreateProgect。选择模版:【OpenHarmony】EmptyAbility:填写项目名,shici,应用包名com.nut.shici,应用存储位置XXX(不要有中文,特殊字符,空格)。CompileSDK10,Model:Stage。Device

使用Java的File.renameTo()函数重命名文件在Java编程中,我们经常需要对文件进行重命名的操作。Java提供了File类来处理文件操作,其中的renameTo()函数可以方便地重命名文件。本文将介绍如何使用Java的File.renameTo()函数来重命名文件,并提供相应的代码示例。File.renameTo()函数是File类的一个方法,

使用java的File.getParent()函数获取文件的父路径在Java编程中,我们经常需要操作文件和文件夹。有时候,我们需要获取一个文件的父路径,也就是该文件所在文件夹的路径。Java的File类提供了getParent()方法用于获取文件或文件夹的父路径。File类是Java对文件和文件夹的抽象表示,它提供了一系列操作文件和文件夹的方法。其中,get

使用java的File.getParentFile()函数获取文件的父目录在Java编程中,我们经常需要操作文件和文件夹。当我们需要获取文件的父目录时,可以使用Java提供的File.getParentFile()函数来完成。本文将介绍如何使用这个函数并提供代码示例。Java中的File类是用于操作文件和文件夹的主要类。它提供了许多方法来获取和操作文件的属性

vue3使用element-plus调用message环境:vue3+typescript+element-plus1.全局引入element之后element已经在app.config.globalProperties添加了全局方法$message所以在optionsAPI中可以直接使用mounted(){(thisasany).$message.success("this.$message");}2.在CompositionAPI中setup方法传入了两个变量props和

使用math.Log2函数计算指定数字的以2为底的对数在数学中,对数是一个重要的概念,它描述了一个数与另一个数(所谓的底)的指数关系。其中,以2为底的对数特别常见,并在计算机科学和信息技术领域中经常用到。在Python编程语言中,我们可以使用math库中的log2函数来计算一个数字的以2为底的对数。下面是一个简单的代码示例:importmathdef
