含空格的目录名递归检查音频文件时长脚本问题求助
含空格的目录名递归检查音频文件时长脚本问题求助
嗨,James!你的问题其实是bash脚本里处理含空格文件名/目录名的经典坑,我来帮你梳理下问题根源和解决办法~
首先明确你的问题:你写的递归检查音频时长的脚本,在目录名不含空格时运行正常,但遇到像“dir 1”这种带空格的目录时,脚本会把目录名拆成“dir”和“1”两个独立的变量值,导致后续cd命令出错。你的原脚本如下:
#!/bin/bash for dir in $(find . -type d); do cd $dir for file in *.ogg *.wav *.mp3 do duration=$(ffprobe "$file" 2>&1 | awk '/Duration/ { print $2 }') echo -e "$duration\t$file" done | sort -n cd - > /dev/null done
问题根源
你用for dir in $(find . -type d)这种写法时,shell会默认把find输出的内容按空格、制表符、换行符分割成多个元素,所以带空格的目录名会被拆成好几段,自然就没法正确识别完整的目录路径了。
两种可靠的解决方案
方案一:用find -exec直接处理(更简洁)
让find直接帮你处理目录跳转,避开手动处理目录名的麻烦,写法更简洁:
#!/bin/bash find . -type d -exec bash -c ' cd "$0" for file in *.ogg *.wav *.mp3; do # 过滤掉通配符未匹配到文件的情况 [[ -f "$file" ]] || continue duration=$(ffprobe "$file" 2>&1 | awk '\''/Duration/ { print $2 }'\'') echo -e "$duration\t$file" done | sort -n ' {} \;
方案二:用while read配合find -print0(兼容性更强)
如果需要更灵活的逻辑扩展,推荐用这种方式:find的-print0参数会让输出的目录名以空字符分隔,再用while read -d ''读取,完全避免分割错误:
#!/bin/bash find . -type d -print0 | while IFS= read -r -d '' dir; do # 进入目录失败时直接跳过,避免脚本卡死 cd "$dir" || continue for file in *.ogg *.wav *.mp3; do [[ -f "$file" ]] || continue duration=$(ffprobe "$file" 2>&1 | awk '/Duration/ { print $2 }') echo -e "$duration\t$file" done | sort -n cd - > /dev/null done
额外的小优化
我在脚本里加了[[ -f "$file" ]] || continue这一行——当某个目录里没有匹配的音频文件时,通配符会原样输出(比如*.ogg),这一步可以帮你过滤掉这些无效的“文件名”,避免ffprobe报错。另外,所有涉及文件名/目录名的变量都用双引号""包裹起来,这是bash里处理特殊字符的基本操作哦~
这样修改后,不管目录名里有空格、下划线还是其他特殊字符,脚本都能正常运行啦!
备注:内容来源于stack exchange,提问作者JamesB
相关产品推荐
相关产品推荐

