命令行如何查找多个字符串的有序公共子串用于批量重命名
解答
/usr/bin 路径下没有专门用来计算多字符串有序公共子串的独立专用工具,但依托系统默认预装的基础命令(全部位于标准系统路径中,无需额外安装),几十行 Bash 就能实现你要的自动识别公共冗余片段、批量重命名的需求,完全不需要依赖第三方工具。
你日常处理音频文件遇到的冗余公共片段,99%都出现在文件名开头(歌手名、专辑名这类)或者结尾(音源标注、网站水印),根本用不着实现复杂的全字符串最长公共子串算法,逐字符横向比对所有文件名就能快速拿到要删除的公共片段,效率足够覆盖日常使用场景,还不容易出误删bug。
可直接复用的批量重命名脚本
把下面的内容保存为 remove_common_prefix.sh,加执行权限后放到 ~/bin 或者 /usr/local/bin 路径下就能全局调用,逻辑仅识别开头公共前缀,不会误改文件名其他位置的内容:
#!/bin/bash # 自动移除当前目录下指定后缀文件的公共文件名前缀,默认处理.flac文件 shopt -s nullglob suffix=${1:-flac} files=(*."$suffix") if [ ${#files[@]} -lt 2 ]; then echo "当前目录下匹配 .$suffix 的文件不足2个,无需处理" exit 0 fi # 逐字符比对取最长公共前缀 prefix="${files[0]}" for file in "${files[@]:1}"; do # 逐位收缩前缀直到和当前文件开头匹配 while [[ "$file" != "$prefix"* ]]; do prefix="${prefix:0:${#prefix}-1}" # 前缀为空直接终止,无公共片段 [ -z "$prefix" ] && break 2 done done if [ -z "$prefix" ]; then echo "未检测到公共文件名前缀,无需重命名" exit 0 fi # 二次确认避免误操作 echo "检测到公共前缀: $prefix" read -p "确认移除该前缀并重命名所有 .$suffix 文件?[y/N] " confirm if [[ "$confirm" =~ ^[Yy]$ ]]; then for file in "${files[@]}"; do newname="${file#"$prefix"}" # 跳过重命名后重名的异常情况 [ -e "$newname" ] && echo "跳过 $file: 目标名 $newname 已存在" && continue mv -v -- "$file" "$newname" done echo "重命名完成" else echo "已取消操作" fi
使用方法
- 切换到存放音频文件的目标目录
- 直接执行脚本,默认处理
.flac格式文件:
remove_common_prefix.sh
- 如果要处理其他后缀的文件,把后缀作为参数传入即可,比如处理mp3:
remove_common_prefix.sh mp3
脚本执行时会先打印检测到的公共前缀,二次确认后才会执行重命名操作,同时会自动跳过重名文件,不会随意改动文件。
补充说明
- 如果有移除公共后缀的需求,只需要把比对逻辑从字符串开头匹配改成结尾匹配,截名的参数展开从
${file#"$prefix"}替换为${file%"$suffix_str"}即可,逻辑完全一致。 - 你之前手写的sed循环存在隐患:如果文件名中间碰巧出现了你要替换的字符串(比如某首歌的歌名里带了歌手名),会把不该删除的内容也替换掉,用前缀匹配截断的写法完全不会出现这个问题。
- 脚本用到的所有命令都是系统默认预装的,没有额外依赖,兼容绝大多数Linux发行版和macOS环境。
- 真要实现任意位置的最长公共子串查找也可以用awk完成逻辑,但对你的重命名场景完全是杀鸡用牛刀——毕竟你本来就只需要删除开头的冗余信息,查找全串公共子串反而容易把歌名里的相同片段误删掉,得不偿失。
内容的提问来源于stack exchange,提问作者exocortex
相关产品推荐
相关产品推荐

