为何重定向ffmpeg stderr到stdout时Bash会吃掉输入隔行首字母?
循环读取文件名时部分文件名首字母缺失(仅配合ffmpeg处理真实文件时出现)
问题重现
脚本代码:
#!/bin/bash while read -r filename; do echo $filename cmd_out=$(ffmpeg -i "$filename" -f null - 2>&1) done < inputs.txt
输入文件inputs.txt内容:
intro.mp3 silence.mp3 outro.mp3 intro2.mp3
实际输出:
intro.mp3 ilence.mp3 outro.mp3 ntro2.mp3
可见silence.mp3和intro2.mp3的首字母丢失。
原因分析
ffmpeg默认会尝试从标准输入(stdin)读取数据,而你的脚本中while read是通过stdin读取inputs.txt的行内容。当第一个循环执行ffmpeg时,ffmpeg会读取stdin中剩余的内容,吃掉了下一行的第一个字符,导致下一次read只能读到缺少首字母的文件名。
只有当文件真实存在时,ffmpeg完成文件分析后才会触发读取stdin的行为;如果文件不存在,ffmpeg直接报错退出,不会读取stdin,因此不会出现该问题。
解决办法
方法1:禁止ffmpeg读取stdin
使用ffmpeg的-nostdin参数,明确阻止它读取标准输入:
#!/bin/bash while read -r filename; do echo $filename cmd_out=$(ffmpeg -nostdin -i "$filename" -f null - 2>&1) done < inputs.txt
方法2:将ffmpeg的stdin重定向到空设备
把ffmpeg的输入源指向/dev/null,让它无数据可读:
#!/bin/bash while read -r filename; do echo $filename cmd_out=$(ffmpeg -i "$filename" -f null - 2>&1 < /dev/null) done < inputs.txt
方法3:使用独立文件描述符读取输入文件
给inputs.txt分配单独的文件描述符(比如3),让read从该描述符读取内容,避免与ffmpeg的stdin冲突:
#!/bin/bash while read -r filename <&3; do echo $filename cmd_out=$(ffmpeg -i "$filename" -f null - 2>&1) done 3< inputs.txt
内容的提问来源于stack exchange,提问作者Tomasz
相关产品推荐
相关产品推荐

