如何在Bash中移除文件名中的_YYYY_MM_DD_HH_MM部分?
问题描述
我们有一批csv和xml格式的文件,文件名分为以下几种格式:
String_YYYY_MM_DD_HH_MM.csv String_YYYY_MM_DD_HH_MM.xml String.xml String.csv
示例文件:
Reference_Categories_2021_02_24_17_14.csv CD_CategoryTree_2021_02_24_17_14.csv New_Categories.xml Mobile_Footnote_2021_03_05_16_21.csv Campaign_Version_2018_09_24_20_00.xml Campaign_new.csv
需要移除文件名中的_YYYY_MM_DD_HH_MM部分,处理后文件名如下:
Reference_Categories.csv CD_CategoryTree.csv New_Categories.xml Mobile_Footnote.csv Campaign_Version.xml Campaign_new.csv
请问如何在Bash中实现该文件名修改操作?
解决方案
方法1:使用Perl风格的rename命令
大部分Linux发行版默认搭载Perl版本的rename,可通过正则匹配完成批量替换:
rename 's/_\d{4}_\d{2}_\d{2}_\d{2}_\d{2}(\.(csv|xml))$/$1/' *.csv *.xml
- 正则规则说明:
_\d{4}_\d{2}_\d{2}_\d{2}_\d{2}:精准匹配_YYYY_MM_DD_HH_MM格式的时间串(\.(csv|xml))$:捕获文件后缀,确保仅处理目标格式文件$1:将匹配到的时间串替换为捕获到的文件后缀,实现时间串移除
方法2:使用util-linux风格的rename命令
部分发行版(如CentOS)使用util-linux版本的rename,可通过通配符匹配替换:
rename '_[0-9][0-9][0-9][0-9]_[0-9][0-9]_[0-9][0-9]_[0-9][0-9]_[0-9][0-9]' '' *.csv *.xml
- 参数说明:
- 第一个参数:用通配符写法匹配
_YYYY_MM_DD_HH_MM格式的时间串 - 第二个参数:空字符串,表示删除匹配到的时间串部分
- 最后指定要处理的文件类型
- 第一个参数:用通配符写法匹配
方法3:Bash原生循环+参数扩展
若不想依赖rename命令,可通过原生Bash循环实现:
for file in *.csv *.xml; do if [[ $file =~ _[0-9]{4}_[0-9]{2}_[0-9]{2}_[0-9]{2}_[0-9]{2}\.(csv|xml)$ ]]; then new_name="${file%_*_*_*_*_*.*}.${file##*.}" mv -- "$file" "$new_name" fi done
- 参数扩展说明:
${file%_*_*_*_*_*.*}:从文件名末尾截断匹配_*_*_*_*_*.*的部分,保留时间串之前的名称${file##*.}:提取文件的后缀名mv -- "$file" "$new_name":重命名文件,--避免文件名以-开头时出现命令解析错误
内容的提问来源于stack exchange,提问作者Anirvan Ray
相关产品推荐
相关产品推荐

