PHP批量文件重命名脚本(支持正则)

如题。

【免责声明】请了解怎么使用和正则的情况下谨慎使用,由此造成的任何后果均与本程序及其作者无关

【使用说明】

格式: rename from to path from是从什么文件名 to是重命名什么文件名 path是哪个文件夹(path可省略,默认为当前文件夹)

【比如】
rename “(\d+)(.*).jpg” “{1}.jpg” {1}代表正则的第一个捕获组,{2},{3}以此类推
rename “(\d+).jpg” “{i}.jpg” {i}代表从1开始每个文件增加1,{i10}代表从10开始每个文件加1,{i10+2}代表从10开始加2,{i10-2}代表从10开始减2

【另外】
--rsort代表文件名按倒序处理,默认为正序; --debug代表调试,可以打印出哪个文件将会重命名为什么名称的列表; --help是显示帮助文档

【其他】
默认重命名后的文件在path目录下的renamed目录里,不会重命名原文件,请确认无误后仔细拷贝(如需重命名在源文件上,请加--force参数,该参数请谨慎使用,当出现错误时,文件会被覆盖掉且无法恢复,因此非经过严格测试,确保安全情况下不建议使用)

【代码如下】

#!/usr/bin/php
<?php
//【免责声明】请了解怎么使用和正则的情况下谨慎使用,由此造成的任何后果均与本程序及其作者无关
//PHP批量文件重命名脚本(支持正则)
// 格式: rename from to path from是从什么文件名 to是重命名什么文件名 path是哪个文件夹(path可省略,默认为当前文件夹)
// 比如: rename "(\d+)(.*)\.jpg" "{1}.jpg" {1}代表正则的第一个捕获组,{2},{3}以此类推
//       rename "(\d+).jpg" "{i}.jpg" {i}代表从1开始每个文件增加1,{i10}代表从10开始每个文件加1,{i10+2}代表从10开始加2,{i10-2}代表从10开始减2
// 另外: --rsort代表文件名按倒序处理,默认为正序; --debug代表调试,可以打印出哪个文件将会重命名为什么名称的列表; --help是显示帮助文档
// 默认重命名后的文件在path目录下的renamed目录里,不会重命名原文件,请确认无误后再拷贝(如需重命名在源文件上,请加--force参数,该参数请谨慎使用,当出现错误时,文件会被覆盖掉且无法恢复,因此非经过严格测试,确保安全情况下不建议使用)

if(in_array('--help', $argv)) {
    //显示help菜单
    help();
    exit();
}
//开启调试模式
$debug = 0;
if(in_array('--debug', $argv)) {
    unset($argv[array_search("--debug",$argv,true)]);
    $debug = 1;
}

//开启覆盖式重命名,默认是拷贝式重命名
$forceCover = 0;
if(in_array('--force', $argv)) {
    unset($argv[array_search("--force",$argv,true)]);
    $forceCover = 1;

    //让用户确认是否使用--force参数,防止误操作
    fwrite(STDOUT,'您正在使用--force参数,该参数可能导致文件被覆盖且无法恢复,您确认使用吗?yes使用,no不使用:');
    $confirm = strtolower(trim(fgets(STDIN)));
    if($confirm != 'yes' && $confirm != 'y') {
        //不使用
        $forceCover = 0;
    }
}

//--rsort把文件按自然排序倒序,默认是按自然排序正序
$sortType = 'sort';
if(in_array('--rsort', $argv)) {
    unset($argv[array_search("--rsort",$argv,true)]);
    $sortType = 'rsort';
}

//获取命令行参数,建议加“”防止字符被shell解析
$argv = array_values($argv);
$from = $argv[1]??'';
if($from == "*" || $from == "*.*"){
    $from = ".*";
}
$to = $argv[2]??'';
//path默认为当前目录
$path = $argv[3]??'';
$path = $path ? rtrim($path, '/') . '/' : '';
if(!$from||!$to){
    //参数错误报错并显示帮助
    echo "[error] from and to is required.\n";
    help();
    exit();
}

//遍历所有文件并按自然排序
$files = glob("{$path}*");
if($sortType == 'rsort') {
    rsort($files, SORT_NATURAL);
} else {
    sort($files, SORT_NATURAL);
}

//匹配$to中{i10+1}字符串
preg_match("#\{(?<i>[iI])(?<init>(\d+){0,1})(?<op>[+-]{0,1})(?<step>(\d+){0,1})\}#", $to, $toMatches);

//设置初始值
$init = !empty($toMatches['init']) ? intval($toMatches['init']) : 1;
$count = $init ?: 1;

//遍历所有文件名进行替换处理
foreach ($files as $filename) {
    $tofilename = $to;

    //替换$to中{i10+1}字符串
    if(!empty($toMatches)) {
        $tofilename = str_replace($toMatches[0], $count, $tofilename);
    }

    //替换每个文件名的捕获组(即$from正则中的捕获组)
    preg_match("#{$from}#i", $filename, $fromMatches);
    if(!empty($fromMatches)) {
        foreach($fromMatches as $key => $val) {
            //跳过第一个,第一个不是捕获组
            if($key > 0) {
                $tofilename = str_replace("{{$key}}", $val, $tofilename);
            }
        }
    }

    // 根据$to中{i10+1}字符串判断操作方向
    if(!empty($toMatches)) {
        $step = !empty($toMatches['step']) ? intval($toMatches['step']) : 1;
        $op = !empty($toMatches['op']) ? trim($toMatches['op']) : "+";
        if($op == "+"){
            $count = $count + $step;
        } else {
            $count = $count - $step;
        }
    }

    //调试时只显示不实际写入
    if($debug) {
        $tofilename = $path.$tofilename;
        echo "$filename => $tofilename\n";
        continue;
    }

    //写入重名名后的文件
    if($forceCover){
        //覆盖式重命名
        rename($filename, $path.$tofilename);
    } else {
        //拷贝式重命名
        if(!file_exists($path.'renamed/')){
            mkdir($path.'renamed/',0777,true);
        }
        copy($filename, $path.'renamed/'.$tofilename);
    }
}

function help() {
    echo "帮助文档:\n";
    echo "格式:rename from to path from是从什么文件名 to是重命名什么文件名 path是哪个文件夹(path可省略,默认为当前文件夹)\n";
    echo "列如:rename \"(\d+)(.*)\.jpg\" \"{1}.jpg\" {1}代表正则的第一个捕获组,{2},{3}以此类推\n";
    echo "列如:rename \"(\d+).jpg\" \"{i}.jpg\" {i}代表从1开始每个文件增加1,{i10}代表从10开始每个文件加1,{i10+2}代表从10开始加2,{i10-2}代表从10开始减2\n";
    echo "另外: --rsort代表文件名按倒序处理,默认为正序; --debug代表调试,可以打印出哪个文件将会重命名为什么名称的列表; --help是显示帮助文档\n";
    echo "默认重命名后的文件在path目录下的renamed目录里,不会重命名原文件,请确认无误后再拷贝(如需重命名在源文件上,请加--force参数,该参数请谨慎使用,当出现错误时,文件会被覆盖掉且无法恢复,因此非经过严格测试,确保安全情况下不建议使用)\n";
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!