Bash环境下无需rename函数实现文件名单个数字补零
批量重命名文件:单个数字补零为两位
问题背景
现有一批格式为L2_error_with_G_at_#_#.csv的文件,其中#代表1-16之间的任意数字。需在Bash环境下将文件名中的单个数字补零为两位(例如L2_error_with_G_at_2_9.csv改为L2_error_with_G_at_02_09.csv,L2_error_with_G_at_1_16.csv改为L2_error_with_G_at_01_16.csv),且无法使用Perl版rename工具,需依赖Bash标准工具实现。
原尝试代码:
for file in L2_error_with_G_at_*.csv do new=$(echo "$file" | sed 's/_\([0-9]\)/_0/g; s/_0\([0-9][0-9]\)/_\1/g;'); mv "$file" "$new"; done;
原代码问题分析
原sed命令存在逻辑错误:第一个替换规则s/_\([0-9]\)/_0/g会直接丢弃下划线后的单个数字(比如_2会被替换成_0而非_02),导致文件名丢失关键信息,后续的修正规则也无法挽回错误。
可行解决方案
方案1:修正后的sed实现
调整正则规则,保留原数字并补零,同时避免修改两位数字:
for file in L2_error_with_G_at_*.csv; do new=$(echo "$file" | sed -E 's/_([0-9])_/_0\1_/g; s/_([0-9])\.csv/_0\1.csv/g') mv "$file" "$new" done
-E启用扩展正则表达式,简化语法- 第一个规则匹配
_单个数字_格式,替换为_0单个数字_,处理中间的单个数字 - 第二个规则匹配
_单个数字.csv格式,替换为_0单个数字.csv,处理末尾的单个数字 - 两位数字(如
_16)因不匹配单个数字正则,不会被修改
方案2:纯Bash内置命令实现(无外部工具依赖)
利用Bash字符串处理和格式化功能完成重命名:
prefix="L2_error_with_G_at_" suffix=".csv" for file in "${prefix}"*.${suffix}; do # 提取文件名中的数字部分 nums=${file#${prefix}} nums=${nums%.${suffix}} # 拆分两个数字 num1=${nums%_*} num2=${nums#*_} # 格式化数字为两位(自动补零) printf -v new_num1 "%02d" "$num1" printf -v new_num2 "%02d" "$num2" # 拼接新文件名并重命名 new_file="${prefix}${new_num1}_${new_num2}${suffix}" mv "$file" "$new_file" done
- 通过
${file#prefix}和${file%suffix}移除前后固定内容,提取数字段 - 用
%_*和#*_拆分两个独立数字 printf -v将数字格式化为两位,自动为单个数字补零
方案3:awk实现
通过awk分割文件名并格式化数字:
for file in L2_error_with_G_at_*.csv; do new=$(echo "$file" | awk -F'[_.]' '{printf "%s_%s_%s_%s_%02d_%02d.%s", $1,$2,$3,$4,$5,$6,$7}') mv "$file" "$new" done
- 以
[_.]为分隔符拆分文件名,将其拆分为多个字段 - 保留前4个固定字段,将第5、6个数字字段格式化为两位,最后保留后缀字段
- 拼接成新文件名后执行重命名
内容的提问来源于stack exchange,提问作者David G.
相关产品推荐
相关产品推荐

