Bash正则替换变量值未达预期的原因及注意事项
Bash正则/Glob差异及媒体库整理脚本修正
问题根源:Bash参数展开用的是Glob,不是正则
你写的( - av1)?*\.webm是正则语法,但Bash的参数替换${i/pattern/}里的pattern是文件名通配(Glob)模式,两者语法完全不同:
- 正则里的
?表示「匹配0或1个前置分组」,但Glob里的?是「匹配单个任意字符」 - 正则里的
*表示「匹配0或多个前置字符」,Glob里的*是「匹配任意长度的任意字符」(无锚定的话会匹配任意位置) - 正则里的
()用于分组,Glob默认把()当字面量处理,只有开启extglob扩展后,才能用@()/?()这类语法实现可选、分组逻辑 - 正则里的
\.转义点号,Glob里的点号是字面量,不需要转义
你的原脚本因为混用了正则语法,导致Bash无法正确匹配后缀,替换失败后生成了错误的文件夹名,进而触发报错。
修正后的脚本
#!/bin/bash # 开启扩展通配模式,支持可选匹配逻辑 shopt -s extglob # 开启空通配模式,避免无匹配时出现"*.webm"字面量 shopt -s nullglob for i in *.webm; do # % 锚定字符串末尾,@( - av1|) 匹配" - av1"或空,再匹配.webm J="${i/%@( - av1).webm/}" echo "$J" # 检查文件夹是否存在,不存在再创建 [ ! -d "$J" ] && mkdir "$J" # 将文件移入目标文件夹 mv "$i" "$J/" done
Bash脚本处理文件名的注意事项
- 严格区分Glob和正则:Bash内置的参数替换、
case语句用Glob;grep/sed/awk才用正则,语法不要混用 - 开启必要扩展:
extglob用于复杂匹配(如可选模式),nullglob避免无匹配时的字面量问题 - 始终双引号包裹变量:文件名含空格、特殊字符时,双引号能防止Bash拆分解析错误
- 添加存在性检查:创建文件夹、移动文件前先检查状态,避免重复创建或移动不存在的文件报错
- 先测试匹配逻辑:单独用
echo "${i/%@( - av1).webm/}"测试替换结果,确认正确后再整合到脚本 - 处理特殊字符:若文件名含
!、$等特殊字符,可先用printf "%q" "$i"查看转义形式,确保脚本兼容
内容的提问来源于stack exchange,提问作者Sherdir
相关产品推荐
相关产品推荐

