linux 中文件批量重命名
mv 命令与批量重命名
linux 中文件重命名一般使用 mv 命令来完成。此命令以单个文件为参数将旧文件重命名为一个新的文件。如果要实现批量化重命名操作,用户需要自行编写程序。
实现批量重命名
最简单的实现
file=$(find ./ -name '*test*')
for i in $file;
do mv $i ${i//test/data}
done
上面的实现中首先使用 find 命令来获取需要批量重命名的文件名并存储到变量 file 中。然后遍历变量内容,使用 bash 中的 pattern substitution 功能来生成新的文件名,以此文件名作为 mv 命令的参数来完成重命名工作。
上述实现相当简单,它其实并不完整。文件名列表、待替换的文件名内容与替换字符串可以通过命令行参数来指定,这样就算是一个完整的功能。
这里使用的 bash 模式替换功能并不常见,可以算作是 bash 的一个技巧。虽然能够解决问题,但总有点奇技淫巧的意味。
使用 awk 的实现
使用 awk 来完成相同的功能时,可以使用 awk 来完成文件名的替换并生成命令,然后调用 system 函数执行命令即可。
下面是一个具体的实现:
#!/usr/bin/gawk -f
function parse_regex(string, regex_arg, regex_cmd, sep, array_index)
{
if (string == "" ) {
return 0
}
sep = substr(string, 2, 1)
if (sep ~! /[[:punct:]]/) {
print sep " is invalid" > "/dev/stderr"
return 0
}
array_index = split(string, regex_cmd, sep)
regex_arg["cmd"] = regex_cmd[1]
regex_arg["regex"] = regex_cmd[2]
regex_arg["replace"] = regex_cmd[3]
regex_arg["opt"] = regex_cmd[4]
return array_index;
}
function execute_substitute(string, regex_cmd)
{
if (string == "") {
return ""
}
switch (regex_cmd["cmd"]) {
case "s":
default:
if (regex_cmd["opt"] == "g") {
gsub(regex_cmd["regex"], regex_cmd["replace"], string)
return string
} else {
sub(regex_cmd["regex"], regex_cmd["replace"], string)
return string
}
}
}
BEGIN {
if (!parse_regex(ARGV[1], regex_cmd)) {
print "invalid regex cmd" ARGV[1] >"/dev/stderr"
exit 1
}
for (i = 2; i < ARGC; i++) {
string = execute_substitute(ARGV[i], regex_cmd)
if (string != ARGV[i]) { # add single quote to avoid special character problem
cmd_buffer = "mv -i -v " "'"ARGV[i]"'" " " "'"string"'"
system(cmd_buffer)
}
}
exit 0
}
用户需要在命令行中指定类似于 sed 中的替换命令。这里仅仅实现了 ‘s’ 命令,不过由于时间原因它并不是一个很严格的实现。
程序首先解析用户指定的替换命令,将字符串切割并放到一个哈希数组中。解析成功后首先执行替换,然后使用替换的结果生成命令行,调用 system 执行命令即可完成重命名工作。依次遍历命令行参数中指定的文件名来批量重命名文件。
运行示例如下:
[longyu@debian:17:00:23] awk $ ./rename.awk 's;awk;gawk;' *
"alarm.ggawk分析.md" -> "alarm.gggawk分析.md"
"anagram.ggawk分析" -> "anagram.gggawk分析"
"egrep-ggawk分析.md" -> "egrep-gggawk分析.md"
"ggawksed分析.md" -> "gggawksed分析.md"
"使用ggawk生成代码的两种不同方式.md" -> "使用gggawk生成代码的两种不同方式.md"
使用 rename 命令
最近发现了一个更为方便的脚本——rename。它是一个 perl 脚本,支持批量重命名工作,并且支持使用 perl 风格的正则替换命令,功能十分强大。
研究发现这个脚本使用了 perl File 模块中的 Rename 功能,更详细的信息请自行百度。
下面是 manual 中的两个示例:
rename 's/\e.bak$//' *.bak # 移除当前目录中后缀为 .bak 的文件名的后缀
rename 'y/A-Z/a-z/' * # 将当前目录中所有文件的文件名中的大写字母转化为小写
该使用哪一种实现呢
在上面的几种实现中,我推荐使用 rename 。需要注意这种批量化操作虽然方便,却可能产生致命的后果,因此执行命令前一定要多测试测试!
更多推荐
所有评论(0)