修改Bash脚本筛选低于320kbps的MP3时遇语法错误求助
解决筛选低码率MP3脚本的语法与比较问题
我来一步步拆解你遇到的问题,帮你修复脚本:
1. 初始脚本的单引号嵌套语法错误
你第一次修改的脚本出现unexpected end of file和找不到匹配符号的问题,核心原因是**单引号的嵌套冲突**: 你用单引号包裹了sh -c的整个命令内容,但里面的awk 'NF>1{print $NF}'`又用了单引号,这会提前闭合外层的单引号,导致shell解析混乱。
比如这段代码的问题点:
sh -c 'curfname="{}";\ bitrate=`mp3info -r a -p "%f %r\n" "$curfname" | awk 'NF>1{print $NF}'`;\ ...'
当shell读到awk '时,就认为外层的单引号已经结束了,后面的内容变成无意义的语法,自然报错。
2. 浮点数比较的错误用法
你去掉awk后,mp3info返回的是浮点数(比如234.544),而[命令(即test命令)只支持整数比较,直接用[ $bitrate -lt 320 ]肯定会报错。
后来你改用bc做浮点数比较,但if [ $(echo "$bitrate < 320" | bc ) -e 1 ]里的-e是用错了——-e是test命令里用来检查文件是否存在的选项,不是用来比较整数的,正确的整数比较应该用-eq(等于)。
修复后的完整脚本
我给你两个可行的版本,你可以根据需求选择:
版本1:直接用mp3info返回的码率(处理浮点数)
这个版本去掉了awk,直接获取mp3info返回的浮点数码率,用bc判断后输出:
find . -maxdepth 1 -iname '*.mp3' -exec sh -c ' curfname="{}" bitrate=$(mp3info -r a -p "%r\n" "$curfname") # 用bc判断浮点数是否小于320,返回1则成立 if [ $(echo "$bitrate < 320" | bc) -eq 1 ]; then echo "$curfname has $bitrate kbps bitrate" fi ' \; | tee ./lowbitrate.log
版本2:保留awk处理(避免异常输出)
如果担心mp3info偶尔会输出多余内容,可以保留awk来提取最后一个字段,这里要注意对awk的单引号转义:
find . -maxdepth 1 -iname '*.mp3' -exec sh -c ' curfname="{}" # 用$()代替反引号,同时转义awk里的单引号 bitrate=$(mp3info -r a -p "%f %r\n" "$curfname" | awk '\''NF>1{print $NF}'\'') if [ $(echo "$bitrate < 320" | bc) -eq 1 ]; then echo "$curfname has $bitrate kbps bitrate" fi ' \; | tee ./lowbitrate.log
关键修复点总结
- 单引号嵌套时,要么用
\'转义内层单引号,要么把外层换成双引号(注意双引号里的变量会被提前解析,这里用单引号包裹sh -c内容更安全)。 - 浮点数比较必须用
bc或awk这类工具,不能直接用[命令;bc返回的是字符串形式的1/0,要用-eq来和整数比较。
内容的提问来源于stack exchange,提问作者R Kon
相关产品推荐
相关产品推荐

