FFmpeg批量转换MKV至MP4的脚本问题求助
你好,我来帮你排查这个批量转换脚本的问题,先从你提到的几个点和脚本里的错误逐一分析:
一、先解答你关心的语法有效性问题
你提到的${file/%mkv/mp4}是完全有效的,这是Bash的后缀替换语法,会精准把文件名末尾的mkv替换成mp4,比如show.mkv会变成show.mp4,这部分你没写错。
而$inpath$file语法上本身是合法的,但存在安全隐患和脚本前置错误,具体往下看:
二、脚本里的核心错误
1. 变量赋值的语法错误
你写的inpath = "~/private/rtorrent/data/"这一行有致命问题:Bash中变量赋值时等号两边绝对不能有空格,否则Bash会把inpath当成一个命令去执行,直接抛出“command not found”的错误。
正确的写法必须去掉空格:
inpath="~/private/rtorrent/data/"
2. 变量引用的安全性问题
$inpath$file的写法在文件名/路径不含空格、特殊字符时能工作,但一旦遇到带空格的文件名(比如My Show.mkv),Bash会把它拆成多个参数传递给FFmpeg,导致FFmpeg无法识别正确的输入文件。
解决办法是用双引号把完整路径包裹起来,确保Bash把它当成一个完整的参数:
# 正确的输入路径写法 "$inpath$file"
另外注意:如果你的inpath末尾没有加/,那就要写成"$inpath/$file",避免出现类似datashow.mkv这种错误的拼接路径。
3. 输出目录未指定(符合你的需求)
你提到要把转换后的MP4放到不同的文件夹,但当前脚本里的${file/%mkv/mp4}是把文件输出到你cd进入的~/private/tv/017目录里,和执行脚本的目录一致。
要指定输出目录,你需要先创建目标目录(避免目录不存在报错),然后在输出路径里加上目录前缀:
# 定义你要输出的目标目录 output_dir="~/private/converted_mp4/" # 自动创建目录(如果不存在的话) mkdir -p "$output_dir" # 输出路径拼接成目录+转换后的文件名 "$output_dir${file/%mkv/mp4}"
三、修复后的完整脚本
把所有问题修正后,加上一些防报错的细节(比如防止cd失败、防止无MKV文件时的错误处理),最终脚本如下:
# 切换到指定目录,如果切换失败就直接退出脚本,避免后续错误 cd ~/private/tv/017 || exit # 定义输入文件所在目录 inpath="~/private/rtorrent/data/" # 定义输出文件的目标目录,替换成你实际想要的路径 output_dir="~/private/converted_mp4/" # 确保输出目录存在 mkdir -p "$output_dir" # 遍历当前目录下的所有MKV文件 for file in *.mkv; do # 如果当前的"file"不是真实文件(比如目录下无MKV时,*.mkv会被当成字符串),就跳过 [ -f "$file" ] || continue # 执行FFmpeg转换 ffmpeg -threads 1 -i "$inpath$file" \ -map 0 -c:v copy -c:a aac -c:s mov_text -movflags +faststart \ "$output_dir${file/%mkv/mp4}" done
备注:内容来源于stack exchange,提问作者pbb

