欢迎光临!请记住我的域名:http://wish123.cnblogs.com
代码改变世界

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

2023-03-22 21:56  wish123  阅读(50)  评论(0编辑  收藏  举报

如题。

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

格式: 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 参数,该参数请谨慎使用,当出现错误时,文件会被覆盖掉且无法恢复,因此非经过严格测试,确保安全情况下不建议使用)

【代码如下】

  1 #!/usr/bin/php
  2 <?php
  3 //【免责声明】请了解怎么使用和正则的情况下谨慎使用,由此造成的任何后果均与本程序及其作者无关
  4 //PHP批量文件重命名脚本(支持正则)
  5 // 格式: rename from to path from是从什么文件名 to是重命名什么文件名 path是哪个文件夹(path可省略,默认为当前文件夹)
  6 // 比如: rename "(\d+)(.*)\.jpg" "{1}.jpg" {1}代表正则的第一个捕获组,{2},{3}以此类推
  7 //       rename "(\d+).jpg" "{i}.jpg" {i}代表从1开始每个文件增加1,{i10}代表从10开始每个文件加1,{i10+2}代表从10开始加2,{i10-2}代表从10开始减2
  8 // 另外: --rsort代表文件名按倒序处理,默认为正序 --debug代表调试,可以打印出哪个文件将会重命名为什么名称的列表 --help是显示帮助文档
  9 // 默认重命名后的文件在path目录下的renamed目录里,不会重命名原文件,请确认无误后再拷贝(如需重命名在源文件上,请加--force参数,该参数请谨慎使用,当出现错误时,文件会被覆盖掉且无法恢复,因此非经过严格测试,确保安全情况下不建议使用)
 10 
 11 if(in_array('--help', $argv)) {
 12     //显示help菜单
 13     help();
 14     exit();
 15 }
 16 //开启调试模式
 17 $debug = 0;
 18 if(in_array('--debug', $argv)) {
 19     unset($argv[array_search("--debug",$argv,true)]);
 20     $debug = 1;
 21 }
 22 
 23 //开启覆盖式重命名,默认是拷贝式重命名
 24 $forceCover = 0;
 25 if(in_array('--force', $argv)) {
 26     unset($argv[array_search("--force",$argv,true)]);
 27     $forceCover = 1;
 28 
 29     //让用户确认是否使用--force参数,防止误操作
 30     fwrite(STDOUT,'您正在使用--force参数,该参数可能导致文件被覆盖且无法恢复,您确认使用吗?yes使用,no不使用:');
 31     $confirm = strtolower(trim(fgets(STDIN)));
 32     if($confirm != 'yes' && $confirm != 'y') {
 33         //不使用
 34         $forceCover = 0;
 35     }
 36 }
 37 
 38 //--rsort把文件按自然排序倒序,默认是按自然排序正序
 39 $sortType = 'sort';
 40 if(in_array('--rsort', $argv)) {
 41     unset($argv[array_search("--rsort",$argv,true)]);
 42     $sortType = 'rsort';
 43 }
 44 
 45 //获取命令行参数,建议加“”防止字符被shell解析
 46 $argv = array_values($argv);
 47 $from = $argv[1]??'';
 48 if($from == "*" || $from == "*.*"){
 49     $from = ".*";
 50 }
 51 $to = $argv[2]??'';
 52 //path默认为当前目录
 53 $path = $argv[3]??'';
 54 $path = $path ? rtrim($path, '/') . '/' : '';
 55 if(!$from||!$to){
 56     //参数错误报错并显示帮助
 57     echo "[error] from and to is required.\n";
 58     help();
 59     exit();
 60 }
 61 
 62 //遍历所有文件并按自然排序
 63 $files = glob("{$path}*");
 64 if($sortType == 'rsort') {
 65     rsort($files, SORT_NATURAL);
 66 } else {
 67     sort($files, SORT_NATURAL);
 68 }
 69 
 70 //匹配$to中{i10+1}字符串
 71 preg_match("#\{(?<i>[iI])(?<init>(\d+){0,1})(?<op>[+-]{0,1})(?<step>(\d+){0,1})\}#", $to, $toMatches);
 72 
 73 //设置初始值
 74 $init = !empty($toMatches['init']) ? intval($toMatches['init']) : 1;
 75 $count = $init ?: 1;
 76 
 77 //遍历所有文件名进行替换处理
 78 foreach ($files as $filename) {
 79     $tofilename = $to;
 80 
 81     //替换$to中{i10+1}字符串
 82     if(!empty($toMatches)) {
 83         $tofilename = str_replace($toMatches[0], $count, $tofilename);
 84     }
 85 
 86     //替换每个文件名的捕获组(即$from正则中的捕获组)
 87     preg_match("#{$from}#i", $filename, $fromMatches);
 88     if(!empty($fromMatches)) {
 89         foreach($fromMatches as $key => $val) {
 90             //跳过第一个,第一个不是捕获组
 91             if($key > 0) {
 92                 $tofilename = str_replace("{{$key}}", $val, $tofilename);
 93             }
 94         }
 95     }
 96 
 97     // 根据$to中{i10+1}字符串判断操作方向
 98     if(!empty($toMatches)) {
 99         $step = !empty($toMatches['step']) ? intval($toMatches['step']) : 1;
100         $op = !empty($toMatches['op']) ? trim($toMatches['op']) : "+";
101         if($op == "+"){
102             $count = $count + $step;
103         } else {
104             $count = $count - $step;
105         }
106     }
107 
108     //调试时只显示不实际写入
109     if($debug) {
110         $tofilename = $path.$tofilename;
111         echo "$filename => $tofilename\n";
112         continue;
113     }
114 
115     //写入重名名后的文件
116     if($forceCover){
117         //覆盖式重命名
118         rename($filename, $path.$tofilename);
119     } else {
120         //拷贝式重命名
121         if(!file_exists($path.'renamed/')){
122             mkdir($path.'renamed/',0777,true);
123         }
124         copy($filename, $path.'renamed/'.$tofilename);
125     }
126 }
127 
128 function help() {
129     echo "帮助文档:\n";
130     echo "格式:rename from to path from是从什么文件名 to是重命名什么文件名 path是哪个文件夹(path可省略,默认为当前文件夹)\n";
131     echo "列如:rename \"(\d+)(.*)\.jpg\" \"{1}.jpg\" {1}代表正则的第一个捕获组,{2},{3}以此类推\n";
132     echo "列如:rename \"(\d+).jpg\" \"{i}.jpg\" {i}代表从1开始每个文件增加1,{i10}代表从10开始每个文件加1,{i10+2}代表从10开始加2,{i10-2}代表从10开始减2\n";
133     echo "另外: --rsort代表文件名按倒序处理,默认为正序 --debug代表调试,可以打印出哪个文件将会重命名为什么名称的列表 --help是显示帮助文档\n";
134     echo "默认重命名后的文件在path目录下的renamed目录里,不会重命名原文件,请确认无误后再拷贝(如需重命名在源文件上,请加--force参数,该参数请谨慎使用,当出现错误时,文件会被覆盖掉且无法恢复,因此非经过严格测试,确保安全情况下不建议使用)\n";
135 }