linux下批量重命名目录及子目录下的文件
一 、加上后缀名
假如只是给当前目录及所有子目录下的文件添加后缀名,使用 find 和 mv 就可以了。
比如把当前及子目录下所有带 _test 后缀的文件加上 .c 后缀
find . -type f -name '*_test' -exec mv {} {}.c \;
- find . 查找当前及子目录,GNU版本的find也可以省略点号,效果一样。
- -type f 指定普通文件类型 【-type d 则指定目录】
- -name '*_test' 指定以 _test 后缀的文件名,* 匹配 0 个或多个字符,这里需要注意的是test后面加星号可以修改test在文件名中间的情况,不加星号则代表它就在文件名末尾。
- 单引号是强引用,保证星号在传递给find 时不会被shell解释,即将字面含义的星号传入find,find后将其解释为通配符。在这里可以使用反斜杠,即
\*_test = '*_test'
,这里涉及到引用和转义及强弱引用的知识。
简单来说就是
- 反斜线引用单个字符(也称为转义了这个字符)
- 单引号引用一串字符
- 双引号引用一串字符,但是保留$(美元)、`(反引号)、(反斜线)的特殊含义
如ls *.c
显示所有后缀名为 .c 的文件,但ls '*.c'
显示字面意义上的 *.c文件,星号在这里被引用为字面上的 * 号, 失去其通配的含义
- -exec 代表 find 的动作(action),语法为
-exec command {} \;
执行command, {} 指示匹配的文件名(路径名),对一些shell来说可能需要引用花括号-exec command '{}' \;
为了表明 -exec 命令的结尾,必须使用分号;结束命令,同时为了避免被shell解释,又得加上反斜线 \ - mv {} {}.c \; 这里 mv 即上面的 command ,{} 指示 find 查找到的路径名
{}.c 为文件名加上后缀
下面来做个测试
点击查看代码
测试环境
$ Ubuntu 22.04.2 LTS (GNU/Linux 5.15.90.1-microsoft-standard-WSL2 x86_64)
$ touch xx{1,2,3,4,5,6}_test
$ ls
$ xx1_test xx2_test xx3_test xx4_test xx5_test xx6_test
$ find -type f -name '*_test'
$
./xx4_test
./xx3_test
./xx6_test
./xx1_test
./xx2_test
./xx5_test
$ find . -type f -name '*_test' -exec mv {} {}.c \;
$ ls
$
xx1_test.c xx2_test.c xx3_test.c xx4_test.c xx5_test.c xx6_test.c
没有什么问题
-exec的问题是每查找到一个文件,就会执行一次-exec命令,如果查到到六次(上面的情况),就会执行find命令六次,对于操作一小组的文件的简单命令可能没啥问题,但是涉及到大量文件时,效率就比较慢,这时可以将find的输出管道传送到另一个程序,即xargs,这个程序专门处理这种情况。这时,配合rename使用就可以处理更多情况
二、批量修改文件名的任意部分
我的rename程序为Perl版本,提供man rename可以查看版本
像上面那样只是加上后缀名,可以这样
find . -type f -name '*_test' | xargs rename 's/(test)/$1.c/'
- | 为管道线,将find的输出到管道上再作为rename的输入
- xargs使得rename程序可以对find查找到的路径名进行操作
- 's/(test)/$1.c/' Perl版本的正则表达式,s/被替换的字符串/替换时用的字符串/,(test)将字符串包裹起来,然后用后面的$1指代该字符串(在其它正则表达式中,可能是\1而不是$1)
如果想要在_test前面加上log变成_logtest,简单的更改下正则表达式的内容即可
find . -type f -name '*_test' | xargs rename 's/(test)/log$1/'
假如test后面带有数字和后缀名,如_test1.c,_test2.c,_test3.c.....想要将其改成其他后缀名,只需
find . -type f -name '*_test*' | xargs rename 's/(test[0-9]).c)/$1.后缀名/'
这里面有许多花样,取决于对正则表达式的理解程度
进一步阅读:
regular-expressions
Harley Hahns Guide to Unix and Linux
The Linux Command Line