Bash脚本文件名增量异常:19递增为110而非20的修复求助
解决Bash文件名递增时跨10数字识别错误的问题
你的问题核心是正则表达式的贪婪匹配导致数字捕获不完整:原正则里的(.*)会尽可能多的匹配字符,把"V. 19"里的"1"也吃掉,只留给[0-9]+最后一位"9",递增后变成10,拼接后就出现"110"的错误。
修正后的脚本
#!/bin/bash fileName="$1" today=$(date +"%Y-%m-%d") # 匹配带日期和版本号的文件名,精准捕获完整数字 if [[ $fileName =~ ^([0-9]{4}-[0-9]{2}-[0-9]{2})(.*V\. )([0-9]+)\.([^.]+)$ ]]; then # BASH_REMATCH分组说明: # 1 - 日期部分 # 2 - 日期到版本号前缀的内容(如" Letter Application V. ") # 3 - 完整版本数字 # 4 - 文件扩展名 number=$(( ${BASH_REMATCH[3]} + 1 )) # 循环检查新文件名是否存在,避免重复 while :; do newFileName="${today}${BASH_REMATCH[2]}${number}.${BASH_REMATCH[4]}" [[ -f "$newFileName" ]] || break ((number++)) done echo "复制 $fileName 到 $newFileName" cp "$fileName" "$newFileName" # 匹配无日期和版本号的文件名,添加日期和初始版本号 elif [[ $fileName =~ ^(.*)\.([^.]+)$ ]]; then baseName="${BASH_REMATCH[1]}" ext="${BASH_REMATCH[2]}" newNumber=1 addInfoName="${today} ${baseName} V.${newNumber}.${ext}" mv "$fileName" "$addInfoName" ((newNumber++)) cp "$addInfoName" "${today} ${baseName} V.${newNumber}.${ext}" fi
关键修改点
- 正则表达式优化:
- 把原正则的
(.*)([0-9]+)改成(.*V\. )([0-9]+),精准定位版本号前缀"V. ",确保[0-9]+能捕获完整的数字(比如19、29)。 - 给日期部分加上
^开头锚定和{4}/{2}的长度限制,避免误匹配文件名中间的类似日期的字符串。
- 把原正则的
- 变量引用规范:所有文件名变量都用双引号包裹,避免空格导致的错误。
- 递增写法简化:用
((number++))替代let "number++",更符合Bash现代写法。
测试验证
- 输入文件:
2023-09-25 Letter Application V.19.txt - 运行脚本后,生成新文件:
2023-10-28 Letter Application V.20.txt(日期自动替换为当日,数字正常跨10递增) - 无版本号的文件:
Resume.docx - 运行脚本后,会先重命名为
2023-10-28 Resume V.1.docx,再复制出2023-10-28 Resume V.2.docx
内容的提问来源于stack exchange,提问作者ReaderGuy42
相关产品推荐
相关产品推荐

