在Linux下,文件和目录的重命名是一个重要的任务,是一种最基本的操作。批量重命名,一次处理多个文件或目录,能有效提高工作效率,极大地确保工作的质量和效率,减少错误。
Linux下有多种操作,用户可以根据自己的需求,采用不同的方法,进行批量重命名。
一、模拟案例
修改或重命名文件有许多具体的要求,大致相同,我们整理下面的五类,作一分析、研讨与处理。更多地案例可以后续交流。
1.修改当前目录下的.conf文件全部为.txt文件
2.把当前目录下的test开头的文件全部修改为demo开头的文件
3.调整当前目录下子目录下的2022-05-01等含日期的文件为.分隔的文件
4.将当前目录下所有子目录下以a开头的.cpp文件改名为以b开头的.c文件
5.将当前目录下所有子目录下以ab开头的.py文件改名为以AB开头的.sh文件,将所有.jpg文件修改为test_01.jpg等格式(序号按创建文件时间排列)
二、梳理思路
1.查找文件
查找文件是批量处理文件的前提。一般查找时会用到通配符*,表示一类文件。主要方法有ls、find和grep。
a.ls
我们可以通过 ls 命令来获取文件列表。该命令只能获取某个目录中的文件,没办法进行多种条件的筛选。
ls
ls *.txt
b.find
find查找文件功能强大,通过设置不同选项,可查找不同目录下的各类文件。
find *
find ./ -name “*.c”
c.grep
grep是Linux 中常用的搜索工具,配合find更精准地找出需要的文件。grep 则主要用于检索文件内容,通过管道与find结合。
find * |grep ^ab
2.处理方式
a.管道|
我们批量重命名文件,主要有两大步骤:确定有哪些文件,再针对性处理。管道就是两大步骤的桥梁。
ls *.txt | mv a5.txt a5.sh
b.-exec
用find查找文件后,可以利用管道,也可以通-exec命令直接处理查出的数据。
find . –name “*.sh” –exec cp {} {}.bak \;
c.xargs
此命令结合ls find可以把查询结果作为后续命令的参数继续处理。xargs功能强大,使用效率高,很常用。
d.for循环
我们的问题是批量处理文件,这类情况比较适合用for循环来处理。设置好循环条件,对处理对象可以不同方式处理。本方法应用十分普遍。
3.执行命令
a.mv
mv命令主要作为基础命令,各种场合需要。不能作为一个方法使用,只能作为铺垫。
b.rename
这是应用较早的命令,方便、易懂、效率高。随着各种语言的发展,功能拓展很多,也被众多命令所替代。
在centos7中还使用c语言风格的命令。Ubuntu应用perl版本的rename命令,支持正则。
c.prename
如果是使用的centos7系统,自己对正则表达式与sed比较熟悉,推荐下载perl版的重命名命令Prename。功能强,语法简单。
这相当于在centos7上实现perl版本的rename。
d.sed
sed是按行处理文件的强大的文本处理工具。与grep、awk并称为linux三剑客。
使用sed进行标准输出的增删改查。其重要的字符串替换,通用格式如下:
stdout | sed 's/pattern/replace/'
与find xargs grep 等组合,可以支持正则,十分方便对文件名进行替换修改主。
e.awk
使用awk脚本命令,功能强大,几乎什么复杂操作都能放进一个awk命令中完成。
三、实施步骤
1、mv for循环批量更改文件名
对于案例1:
修改当前目录下的.conf文件全部为.txt文件
我们首先用ls *.conf查出文件,然后利用循环处理后缀名。
for file in 'ls *.conf'; do mv $file ${file%.conf}.txt;done
2.prename ls结合完成案例2
对于案例2:
把当前目录下的test开头的文件全部修改为demo开头的文件
我们首先用ls test*
查出文件,然后利用prename对字符串进行替换。
ls test* |prename 's/test/demo/'
3.sed find结合进行文件符号格式修改
对于案例3:
调整当前目录下子目录下的2022-05-01等含日期的文件为.分隔的文件
我们采用的思路是用find查出文件,然后利用for循环。在循环中,显示文件列表,再通过管道、sed和mv对文件中指定符号进行替换。
for f in `find . -name "*.jpg"`;do echo $f | mv $f `sed 's/-/\./g'`;done
命令中,符号-不需要转义,而.是需要的。
下面的命令代码,效果一样。
for file in `ls *.jpg`;do newfile=`echo $file |sed 's/-/\./g'`;mv $file $newfile;done
4.find –exec prename或sed结合进行高级修改
对于案例4:
将当前目录下所有子目录下以a开头的.cpp文件改名为以b开头的.c文件
用find查出文件,不是难事。
如何替换文件名称,可通过-exec和prename:
find ./* -name "a*.cpp" -exec prename 's/(.*\/)a([^\/]*)\.cpp$/$1b$2\.c/' {} \;
结果如下:
5.命令组合解决复杂问题
对于案例5:
将当前目录下所有子目录下以ab开头的.py文件改名为以AB开头的.sh文件,将所有.jpg文件修改为test_01.jpg等格式(序号按创建文件时间排列)
有多种解决办法:每种情况解决一次;一次解决所有问题。我们用prename命令分两次解决问题。
prename命令组合解决.py文件:
find ./* -name "ab*.py" |xargs -i prename 's/(.*\/)ab([^\/]*)\.py$/$1AB$2\.sh/' {}
for组合prename解决.py文件:
for f in `find ./* -name "ab*.py"`;do newf=`echo $f | prename 's/(.*\/)ab([^\/]*)\.py$/$1AB$2\.sh/'`;mv $f $newf;done
for组合awk解决.jpg文件:
find . -name "*.jpg" |awk 'BEGIN{tag = 1} {printf("mv %s test_%02d.jpg\n", $0, tag); tag++}' | bash