Linux rename命令 批量重命名

时间:2022-03-24 10:36:19

Linux rename命令 批量重命名

Linux的 rename 命令有两个版本,一个是C语言版本的,一个是Perl语言版本的,早期的Linux发行版基本上使用的是C语言版本的,现在已经很难见到C语言版本的了,由于历史原因,在Perl语言大红大紫的时候,Linux的工具开发者们信仰Perl能取代C,所以大部分工具原来是C版本的都被Perl改写了,因为Perl版本的支持正则处理,所以功能更加强大,已经不再需要C语言版本的了。

 


如何区分系统里的rename命令是哪个版本的?

输入 man rename 看到第一行是

RENAME(1)                  Linux Programmer’s Manual                  RENAME(1)

那么 这个就是C语言版本的。

而如果出现的是:
RENAME(1)              Perl Programmers Reference Guide              RENAME(1)

这个就是Perl版本的了!


两个版本的语法差异:

C语言的,按照man上面的注解,
rename的语法格式是:

rename  fromtofile

这个命令有三个参数,分别是 from : 修改什么名字, to:改成什么名字, file 需要修改的文件是哪些。

用法示例:
比如,有一批文件,都是以 log开头的, log001.txt,  log002.txt ....... 一直到 log100.txt
现在想要把这批文件的log全部替换为 history 
rename   log history log*

这句命令的意思很明白了,把 以 log开头的所有文件中的 log字符替换为 history
这样替换后的文件是: history001.txt,  history002.txt ..... 一直到 history100.txt

rename C语言版本的另一个man示例是把后缀名批量修改,
比如我们要将所有 jpeg的后缀名图片文件修改为 jpg文件。

rename   .jpeg.jpg*.jpeg

这样,所有以 .jpeg扩展的后缀名全部被修改为 .jpg

现在总结一下rename C语言版本所能实现的功能: 批量修改文件名,结果是每个文件会被用相同的一个字符串替换掉!也就是说,无法实现诸如循环 然后按编号重命名!



2, Perl 版本的批量重命名,带有Perl的好处是,你可以使用正则表达式来完成很奇特的功能。

perl 版本的参数格式:

rename      perlexprfiles

注意,perl版本的rename只有两个参数,第一个参数为perl正则表达式,第二个参数为所要处理的文件

man rename的帮助示例:

1) 有一批文件,以 .bak结尾,现在想把这些 .bak 统统去掉。

rename        's/\.bak$//'       *.bak

这个命令很简单,因为我还没有系统学习过perl,我不知道perl里替换字符串是不是这么干的,但sed是这么干的,所以如果你有sed或者tr基础,很容易明白,这个替换和sed里的正则语法是一模一样的。

2) 把所有文件名内含有大小字母的,修改为小写字母。

rename        'y/A-Z/a-z/'      *

依然和sed的替换语法一样,不用多解释,如果看不懂的话,可以系统学习一下sed先。

还有几个比较实用的例子:

1) 批量去掉文件名里的空格 
Linux文件名本来是不支持空格的,不知道什么时候允许了,当然,在命令行调用文件的时候,空格是很有问题滴,比如你 原来可以直接  mv  oldfile  newfile  但有空格就不行了 , 得加双引号: mv "oldfile"  "newfile" 或者用反斜杠转移  \[] ,这样还好,但如果你直接把含有空格的图片名引入 Latex文档,Latex生成pdf的时候会直接打印出文件名,之前这个问题苦恼了我很久,我生成的pdf怎么老是出现文件名呢?后来才发现原来是文件名内含有空格的问题!windows系统下生成的文件名是天生含有空格的,虽然很讨厌,但有些惠普扫描仪生成的图片默认就加入了空格,没有办法,只好去掉他,在系统研究rename命令前,我是用 mv 去除空格的。

网上流程的两个去空格的版本:

1) tr 版:

find . -type f -name "* *" -print |
while read name; do
na=$(echo $name | tr ' ' '_')
if [[ $name != $na ]]; then
mv "$name" $na
fi
done

这个版本以前我一直用的,不知道哪个网上搜刮来的,当时还没有系统的学习过 tr/sed/awk命令。
注解一下,很好理解, find . type f -name "* *" -print 这一句是查找当前目录下所有类型为普通文件的 并且名字之中含有空格的文件,并打印出来,其实 find默认就是打印的 这个 -print 多余了,然后 通过管道传输给 while 循环读取,文件名放到 name 变量里,用 tr 命令 替换空格为 下划线。 下面判断如果执行后的名称不相同,使用 mv 命令重命名。但这个if判断可有可无,因为find已经查询了所有文件名中含有空格的,那么经过 tr 命令后, $na变量肯定不等于 $name 变量的。

所以这段代码可以简化:

find . -type f -name "* *" |
while read name; do
na=$(echo $name | tr ' ' '_')
mv "$name" "$na" 
done

tr 可以看着是 sed 的一个精简版本,tr 用下划线来替换空格。

还有一个 是 sed 版本实现:

for f in *;do mv "$f" `echo "$f" | sed 's/[ ]\+/_/g' `; done

这里的 sed表达式还可以这样写:

sed 's/[[:space:]]\+/_/g' 

不过记住,sed里的出现一次或多次的加号是需要添加反斜杠的。即:\+

这样就可以了。

好了,这两种办法都太他妈罗嗦了,看看rename实现吧:

rename                          's/[ ]+/_/g'       *

OK就这么简单。
方括号内的空格可以用 [:space:]代替,
即可以写成 's/[[:space:]]+/_/g'

这里注意,rename 采用的是标准perl正则语法,所以无须将 加号转变为反斜杠加号 
即 + 不能修改为 \+,否则替换失败。


还有几个好玩的例子:
比如统一在文件头部添加上 hello  
rename         's/^/hello/'       * 

统一把.html扩展名修改为 .htm 
rename          's/.html$/.htm/'      * 

统一在尾部追加 .zip后缀:
rename          's/$/.zip/'      *

统一去掉.zip后缀:

rename          's/.zip$//'      *

 

规则化数字编号名,比如 1.jpg, 2.jpg ..... 100.jpg , 现在要使文件名全部三位即 1.jpg .... 001.jpg 

运行两次命令:

rename           's/^/00/'          [0-9].jpg     # 这一步把 1.jpg ..... 9.jpg 变幻为 001.jpg .... 009.jpg

rename            's/^/0/'           [0-9][0-9].jpg   # 这一步把 10.jpg ..... 99.jpg 变幻为 010.jpg ..... 090.jpg


Ok ,rename就研究了这么多,暂时不知道如何在rename中引入动态变量,比如 $i++


我测试过 i=0;  rename -n "s/^.*$/$((++i))/"   *  执行后i被自增了1,并非想我想像中那样,可以在每操作一个文件自增一,猜想可能是因为rename批量实现的,导致++i只计算一次!


-n 用来测试rename过程,并不直接运行,可以查看测试效果后,然后再运行。




原贴:http://www.linuxfly.org/post/300/

 5

[原]Linux下的rename命令 Linux rename命令 批量重命名Linux rename命令 批量重命名linuxing, 16:28 , 网络服务» 虚拟机评论(0)引用(0)阅读(61), Via 本站原创 Linux rename命令 批量重命名Linux rename命令 批量重命名    Dos/Windows下,对文件改名用rename。而书上说,Linux下对文件或目录改名该用mv。我一直也是这样做的,却忽略了Linux下也有个叫rename的命令。都是rename,但功能上就有点差异了。Linux下的rename更像批量改名的工具,是util-linux套件中提供的。

一、基本功能
从mv和rename命令的man文档中,可以看到如下信息:
引用mv - move (rename) files
rename - Rename files

也就是说,mv也能用于改名,但不能实现批量处理(改名时,不支持*等符号的),而rename可以。
rename使用的格式:

$ rename foo foo0 foo?
rename需要提供三个参数,然后才能决定最终结果。
模拟一下man文档的例子,原文件:
引用$ for i in `seq 100`;do touch foo$i;done
$ ls
foo1    foo18  foo27  foo36  foo45  foo54  foo63  foo72  foo81  foo90
foo10   foo19  foo28  foo37  foo46  foo55  foo64  foo73  foo82  foo91
foo100  foo2   foo29  foo38  foo47  foo56  foo65  foo74  foo83  foo92
foo11   foo20  foo3   foo39  foo48  foo57  foo66  foo75  foo84  foo93
foo12   foo21  foo30  foo4   foo49  foo58  foo67  foo76  foo85  foo94
foo13   foo22  foo31  foo40  foo5   foo59  foo68  foo77  foo86  foo95
foo14   foo23  foo32  foo41  foo50  foo6   foo69  foo78  foo87  foo96
foo15   foo24  foo33  foo42  foo51  foo60  foo7   foo79  foo88  foo97
foo16   foo25  foo34  foo43  foo52  foo61  foo70  foo8   foo89  foo98
foo17   foo26  foo35  foo44  foo53  foo62  foo71  foo80  foo9   foo99

改名结果:
(红色是没有改动的,蓝色是有改动的一部分)
引用$ rename foo foo0 foo?
$ ls
foo01  foo100  foo20  foo30  foo40  foo50  foo60  foo70  foo80  foo90
foo02  foo11   foo21  foo31  foo41  foo51  foo61  foo71  foo81  foo91
foo03  foo12   foo22  foo32  foo42  foo52  foo62  foo72  foo82  foo92
foo04  foo13   foo23  foo33  foo43  foo53  foo63  foo73  foo83  foo93
foo05  foo14   foo24  foo34  foo44  foo54  foo64  foo74  foo84  foo94
foo06  foo15   foo25  foo35  foo45  foo55  foo65  foo75  foo85  foo95
foo07  foo16   foo26  foo36  foo46  foo56  foo66  foo76  foo86  foo96
foo08  foo17   foo27  foo37  foo47  foo57  foo67  foo77  foo87  foo97
foo09  foo18   foo28  foo38  foo48  foo58  foo68  foo78  foo88  foo98
foo10  foo19   foo29  foo39  foo49  foo59  foo69  foo79  foo89  foo99
$ rename foo foo0 foo??
$ ls
foo001  foo011  foo021  foo031  foo041  foo051  foo061  foo071  foo081  foo091
foo002  foo012  foo022  foo032  foo042  foo052  foo062  foo072  foo082  foo092
foo003  foo013  foo023  foo033  foo043  foo053  foo063  foo073  foo083  foo093
foo004  foo014  foo024  foo034  foo044  foo054  foo064  foo074  foo084  foo094
foo005  foo015  foo025  foo035  foo045  foo055  foo065  foo075  foo085  foo095
foo006  foo016  foo026  foo036  foo046  foo056  foo066  foo076  foo086  foo096
foo007  foo017  foo027  foo037  foo047  foo057  foo067  foo077  foo087  foo097
foo008  foo018  foo028  foo038  foo048  foo058  foo068  foo078  foo088  foo098
foo009  foo019  foo029  foo039  foo049  foo059  foo069  foo079  foo089  foo099
foo010  foo020  foo030  foo040  foo050  foo060  foo070  foo080  foo090  foo100

该例子给出了两种文件批量重命名的用法:
引用第一个参数:被替换掉的字符串
第二个参数:替换成的字符串
第三个参数:匹配要替换的文件模式

rename支持通配符,基本的通配符有以下几个:
引用?    可替代单个字符
*    可替代多个字符
[charset]    可替代charset集中的任意单个字符

二、其他例子
看看*的作用:
引用$ rm -f *
$ for i in `seq 100`;do touch foo$i;done
$ rename foo foo0 foo*
$ ls
foo01    foo018  foo027  foo036  foo045  foo054  foo063  foo072  foo081  foo090
foo010   foo019  foo028  foo037  foo046  foo055  foo064  foo073  foo082  foo091
foo0100  foo02   foo029  foo038  foo047  foo056  foo065  foo074  foo083  foo092
foo011   foo020  foo03   foo039  foo048  foo057  foo066  foo075  foo084  foo093
foo012   foo021  foo030  foo04   foo049  foo058  foo067  foo076  foo085  foo094
foo013   foo022  foo031  foo040  foo05   foo059  foo068  foo077  foo086  foo095
foo014   foo023  foo032  foo041  foo050  foo06   foo069  foo078  foo087  foo096
foo015   foo024  foo033  foo042  foo051  foo060  foo07   foo079  foo088  foo097
foo016   foo025  foo034  foo043  foo052  foo061  foo070  foo08   foo089  foo098
foo017   foo026  foo035  foo044  foo053  foo062  foo071  foo080  foo09   foo099

再看看[charset]的作用:
引用$ rm -f *
$ for i in `seq 100`;do touch foo$i;done
$ rename foo foo0 foo[9]*
$ ls
foo09   foo099  foo17  foo26  foo35  foo44  foo53  foo62  foo71  foo80
foo090  foo1    foo18  foo27  foo36  foo45  foo54  foo63  foo72  foo81
foo091  foo10   foo19  foo28  foo37  foo46  foo55  foo64  foo73  foo82
foo092  foo100  foo2   foo29  foo38  foo47  foo56  foo65  foo74  foo83
foo093  foo11   foo20  foo3   foo39  foo48  foo57  foo66  foo75  foo84
foo094  foo12   foo21  foo30  foo4   foo49  foo58  foo67  foo76  foo85
foo095  foo13   foo22  foo31  foo40  foo5   foo59  foo68  foo77  foo86
foo096  foo14   foo23  foo32  foo41  foo50  foo6   foo69  foo78  foo87
foo097  foo15   foo24  foo33  foo42  foo51  foo60  foo7   foo79  foo88
foo098  foo16   foo25  foo34  foo43  foo52  foo61  foo70  foo8   foo89

不难理解吧,找环境测试一下就明白了。用rename可以减少部分写for循环的工作,还是比较方便的。