Ubuntu 16.04遍历子文件夹批量转码MP4脚本报错解决方案咨询
解决Ubuntu 16.04下多层文件夹批量转码MP4的脚本错误问题
我帮你分析下这个问题哈,你碰到的ENOENT: no such file or directory, stat '*.mp4'错误主要有两个原因,咱们一步一步来解决:
首先是脚本的语法问题
你写的脚本里,cd "$D"后面没有加分号或者换行,导致它和后面的for i in *.mp4连在一起,shell解析的时候会出错,这是第一个要修正的点。
其次是空目录的处理问题
当某个子目录里没有.mp4文件时,for i in *.mp4不会自动跳过,而是会把*.mp4当作一个实际的文件名去查找,自然就会报“找不到文件”的错误。
修正后的基础脚本
咱们先把语法和空目录问题解决,修改后的脚本如下:
shopt -s nullglob # 开启nullglob,当通配符匹配不到文件时会返回空,而不是保留原字符串 for D in ./*; do if [ -d "$D" ]; then cd "$D" || continue # 如果cd失败(比如权限问题),直接跳过当前目录 for i in *.mp4; do # 注意:这里先改成带后缀的文件名测试,避免直接覆盖原文件 ffmpeg -i "$i" -codec copy -acodec copy -shortest -map 0:v -map 0:m:language:eng "${i%.*}_fixed.mp4" done cd .. fi done shopt -u nullglob # 关闭nullglob,避免影响后续操作
解释下关键改动:
- 加入
shopt -s nullglob:开启后,当*.mp4匹配不到文件时,循环不会执行,自然就不会报错 - 在
cd "$D"后面加了|| continue:如果切换目录失败(比如权限不足),直接跳过这个目录,避免后续操作出错 - 把输出文件名改成了
${i%.*}_fixed.mp4:防止直接覆盖原文件,测试没问题后你再改成原文件名
更高效的替代方案:用find命令递归处理
其实不用手动写嵌套循环,find命令可以直接递归遍历所有子目录里的.mp4文件,更简洁可靠,命令如下:
find . -type f -name "*.mp4" -exec sh -c ' for file do # 同样,先改成带后缀的文件名测试 output="${file%.*}_fixed.mp4" ffmpeg -i "$file" -codec copy -acodec copy -shortest -map 0:v -map 0:m:language:eng "$output" # 如果测试没问题,想要覆盖原文件,可以把上面的output改成$file,然后加-y参数强制覆盖: # ffmpeg -y -i "$file" -codec copy -acodec copy -shortest -map 0:v -map 0:m:language:eng "$file" done ' sh {} +
这个命令的优势:
- 自动递归所有子目录,不管层级有多深
- 只会处理实际存在的
.mp4文件,不会出现空匹配的问题 - 用
-exec ... {} +可以批量传递文件,比逐个处理更高效
最后别忘了测试的时候先不要覆盖原文件,确认转码后的文件没问题再替换哦!
内容的提问来源于stack exchange,提问作者Adrixa
相关产品推荐
相关产品推荐

