照片文件、视频文件按拍摄日期重命名

阅读 (266)
最近在备份儿子这几年照片和视频的时候出了点情况,有些照片视频之前换手机前都是备份在路由器外接的移动硬盘上的,有时候上传了又下载回手机,有些照片与视频都无法直观的看出拍摄时间,甚至有些命名以日期命名的,但一看就是错的,明明是夏天的视频,文件名却显示的冬天拍摄的

先申明,本文不是提供工具软件帮你直接修改文件名的,是PHP编程,程序编程,如果是搜工具来的,可以跳过,继续找别的工具了。

本来是想在网上找些软件直接修改一下算了,结果找了好久没找到合适的软件,想想还不如自己PHP写一下算了。说干就干,其实也没多难,还比下载的好用。

思路是先遍历目录文件,有如有子目录就递归遍历,把照片或视频归类好后,分别放到一个目录中,例如photo、video目录中。

图片重命名比较简单,php有exif拓展,直接开启使用 exif_read_data 读图片信息就行。读到时间后格式化一个格式再 rename 函数重命名即可。

图片信息中,我们可用到的一共四个可用到时间信息:

DateTimeOriginal 媒体拍摄时间
GPSDateStamp GSP定位的时间 (一般也是在拍摄时带入的)
DateTime 这个时间在某些时候晚于DateTimeOriginal, 可能是后期被修改的时间,比如美图修改后,可能时间就变了
FileDateTime 文件创建时间(创建时间就更不靠谱了)

photo_rename.php

<?php
// 遍历目录中所有文件,包括子目录中的文件
function read_all ($dir){
    if(!is_dir($dir)) return false;

    $handle = opendir($dir);

    if($handle){
        $count = 0;
        while(($fl = readdir($handle)) !== false){
           
            $temp = $dir.DIRECTORY_SEPARATOR.$fl;
            //如果不加  $fl!='.' && $fl != '..'  则会造成把$dir的父级目录也读取出来
            if(is_dir($temp) && $fl!='.' && $fl != '..'){
                $count = 0;
                echo $count.'目录:'.$temp."\n";
                read_all($temp);
            }else{
                if($fl!='.' && $fl != '..'){
                    $count++;
                    echo '文件:'.$temp."\n";
                    // 开启PHP exif拓展,exif_read_data() 函数从 JPEG 或 TIFF 图像文件中读取 EXIF 头信息。这样就可以读取数码相机产生的元数据。
                    $info = exif_read_data($temp);
                    // 获取媒体拍摄时间
                    $tempDateTime = isset($info['DateTimeOriginal']) && $info['DateTimeOriginal'] ? explode(' ', $info['DateTimeOriginal']) : [];
                    // 由于获取到的时间年月日是用 : 间隔的,所以这里替换一下,重新date format
                    $date1 = !empty($tempDateTime) ? date('Ymd',strtotime(str_replace(':','-', $tempDateTime[0]))) .'_'.date('His',strtotime($tempDateTime[1])) : '';
                    
                    // 获取gps时间信息备用
                    $date2 = isset($info['GPSDateStamp']) && $info['GPSDateStamp'] ? date('Ymd_His',strtotime(str_replace(':','-', $info['GPSDateStamp']))) : '';

                    // 取DateTime字段备用
                    $tempDateTime = isset($info['DateTime']) && $info['DateTime'] ? explode(' ', $info['DateTime']) : [];
                    // 以各上面相同的方式格式化
                    $date3 = !empty($tempDateTime) ? date('Ymd',strtotime(str_replace(':','-', $tempDateTime[0]))) .'_'.date('His',strtotime($tempDateTime[1])) : '';
                    
                    // 获取文件创建时间
                    $date4 = date('Ymd_His', $info['FileDateTime']);

                    // 如果实在一个日期都获取到不,到设置一个标记
                    $finalDateTime = 'unknow';
                    // 按优先级赋值,最好的时间是媒体拍摄时间,所以放最后
                    if ($date4) {
                        $finalDateTime = $date4;
                    }
                    if ($date3) {
                        $finalDateTime = $date3;
                    }
                    if ($date2) {
                        $finalDateTime = $date2;
                    }
                    if ($date1) {
                        $finalDateTime = $date1;
                    }
                    // 定义新文件名
                    $newFileName = 'IMG_'.$finalDateTime.'_'.$count;
                    
                    $pathParts = pathinfo($temp);
                   
                    // 重命名文件
                    rename($temp, $pathParts['dirname'].'\\'.$newFileName.'.'.$pathParts['extension']);
                   
                }
            }
        }
    }
}

read_all('E:\视频-照片\photo');

视频的重命名略复杂一丢丢,因为没有自带的拓展可用,需要靠外部插件 exiftool, 这里就不提供下载了,官网上自己下一个就行

下载完,重命名为exiftool.exe,直接丢到C:\Windows目录中待用。

Media Create Date 最优的是用这个时间,但我很多文件这个时间都丢失了,没办法就用后面两个时间
Create Date
Track Create Date

<?php

function read_all ($dir){
    if(!is_dir($dir)) return false;

    $handle = opendir($dir);

    if($handle){
        $count = 0;
        while(($fl = readdir($handle)) !== false){
            $temp = $dir.DIRECTORY_SEPARATOR.$fl;
            //如果不加  $fl!='.' && $fl != '..'  则会造成把$dir的父级目录也读取出来
            if(is_dir($temp) && $fl!='.' && $fl != '..'){
                $count = 0;
                echo $count.'目录:'.$temp."\n";
                read_all($temp);
            }else{
                if($fl!='.' && $fl != '..'){
                    $count++;
                    echo '文件:'.$temp."\n";
                    // 由于我是在自己电脑上用的,就不要去纠结安全性了,直接用exec执行命令返回数据,存到$retval中待用
                    exec('exiftool '.$temp, $retval); 
                    // exec('exiftool -php '.$temp, $retval); // 加上-php可以返回一个php数组,由于我一开始没细看文档,直接用了,后面的代码也是直接解析了,所以就没用这个参数,如果用了,但后面的代码也要改
                    $tempDateTime1 = [];
                    $tempDateTime2 = [];
                    $tempDateTime3 = [];
                    // exiftool返回了一大堆信息
                    foreach($retval as $key => $val) {
                        // 按空格冒号空格拆成键值对
                        $info = explode(' : ', $val);
                        $infoKey = $info[0]; // 键
                        $infoVal = $info[1]; // 值
                        // 媒体拍摄时间
                        if(trim($infoKey) == 'Media Create Date') {
                            $tempDateTime1 = $infoVal ? explode(' ', $infoVal) : [];
                        }
                        // 创建时间
                        if(trim($infoKey) == 'Create Date') {
                            $tempDateTime2 = $infoVal ? explode(' ', $infoVal) : [];
                        }
                        // 这个不太理解是什么时间
                        if(trim($infoKey) == 'Track Create Date') {
                            $tempDateTime3 = $infoVal ? explode(' ', $infoVal) : [];
                        }
                        
                    }
                    
                    $date1 = !empty($tempDateTime1) && $tempDateTime1[0] != '0000:00:00' ? date('Ymd',strtotime(str_replace(':','-', $tempDateTime1[0]))) .'_'.date('His',strtotime($tempDateTime1[1])) : '';
                    $date2 = !empty($tempDateTime2) && $tempDateTime2[0] != '0000:00:00' ? date('Ymd',strtotime(str_replace(':','-', $tempDateTime2[0]))) .'_'.date('His',strtotime($tempDateTime2[1])) : '';
                    $date3 = !empty($tempDateTime3) && $tempDateTime3[0] != '0000:00:00' ? date('Ymd',strtotime(str_replace(':','-', $tempDateTime3[0]))) .'_'.date('His',strtotime($tempDateTime3[1])) : '';
                    $finalDateTime = 'unknow';
                    if ($date3) {
                        $finalDateTime = $date3;
                    }
                    if ($date2) {
                        $finalDateTime = $date2;
                    }
                    if ($date1) {
                        $finalDateTime = $date1;
                    }
                    
                    $newFileName = 'VID_'.$finalDateTime.'_'.$count;
                    
                    $pathParts = pathinfo($temp);
                    rename($temp, $pathParts['dirname'].'\\'.$newFileName.'.'.$pathParts['extension']);

                    $retval = '';
                }
            }
        }
    }
}

read_all('E:\视频-照片\video');

视频的时间在读不到具体拍摄时间的情况下,也只能做到这种程度了,有一些视频时间是exiftool识别不出来的,windows上右键查看文件属性信息也看不到,但在360云盘上,有几个在windows上没有,但360云却是识别出来了,有空再研究一下。

更新于:2021-01-08 17:05:36
返回顶部