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

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



To learn more about open source, please visit: 51CTO Hongmeng Developer Community https://ost.51cto.com Running environment DAYU200:4.0.10.16SDK: 4.0.10.15IDE: 4.0.600 1. To create an application, click File- >newFile->CreateProgect. Select template: [OpenHarmony] EmptyAbility: Fill in the project name, shici, application package name com.nut.shici, and application storage location XXX (no Chinese, special characters, or spaces). CompileSDK10, Model: Stage. Device

Use Java's File.length() function to get the size of a file. File size is a very common requirement when dealing with file operations. Java provides a very convenient way to get the size of a file, that is, using the length() method of the File class. . This article will introduce how to use this method to get the size of a file and give corresponding code examples. First, we need to create a File object to represent the file we want to get the size of. Here is how to create a File object: Filef

How to convert php blob to file: 1. Create a php sample file; 2. Through "function blobToFile(blob) {return new File([blob], 'screenshot.png', { type: 'image/jpeg' })} ” method can be used to convert Blob to File.

Use Java's File.renameTo() function to rename files. In Java programming, we often need to rename files. Java provides the File class to handle file operations, and its renameTo() function can easily rename files. This article will introduce how to use Java's File.renameTo() function to rename files and provide corresponding code examples. The File.renameTo() function is a method of the File class.

Use java's File.getParentFile() function to get the parent directory of a file. In Java programming, we often need to operate files and folders. When we need to get the parent directory of a file, we can use the File.getParentFile() function provided by Java. This article explains how to use this function and provides code examples. File class in Java is the main class used to operate files and folders. It provides many methods to obtain and manipulate file properties

Use java's File.getParent() function to get the parent path of a file. In Java programming, we often need to operate files and folders. Sometimes, we need to get the parent path of a file, which is the path of the folder where the file is located. Java's File class provides the getParent() method to obtain the parent path of a file or folder. The File class is Java's abstract representation of files and folders. It provides a series of methods for operating files and folders. Among them, get

Use the math.Log2 function to calculate the base 2 logarithm of a specified number. In mathematics, the logarithm is an important concept that describes the exponential relationship of one number to another number (the so-called base). Among them, the base 2 logarithm is particularly common and is frequently used in the fields of computer science and information technology. In the Python programming language, we can calculate the base 2 logarithm of a number using the log2 function from the math library. Here is a simple code example: importmathdef

vue3 uses element-plus to call the message environment: vue3+typescript+element-plus1. After the global introduction of element, element has added the global method $message in app.config.globalProperties, so you can use mounted(){(thisasany) directly in the optionsAPI. $message.success("this.$message");}2. In the compositionAPI, the setup method passes in two variables props and
