在我的 bash 脚本中,我有一个 while 循环,如下所示。我不明白的是,为什么 HandBrakeCLI 的调用会打破循环。如果“if”条件为假并且遵循“else”,则循环继续。这是我的脚本:
FILES="xxx*.ts
yyy.ts"
for f in $FILES
do
find /pathto -name $f -print | while IFS= read -r file; do
echo "file found = $file"
outputfile=$outputpath$(basename "$file")".mp4"
if [[ ! -f $outputfile ]] then
HandBrakeCLI -i "$file" -o "$outputfile" -e x264 -q 22 -r 15 -B 64 -X 480 -O
else echo "outputfile already exists: $outputfile"
fi
done
done
所以我有三个文件,名为 xxx1.ts、xxx2.ts 和 yyy.ts。所有这些都应该由 HandBrakeCLI 找到并转换。但在第一次转换(xxx1.ts)之后,while 循环中断并处理 yyy.ts。如果我再次启动脚本,它会发现第一个文件已经被转换并进入 else 分支。这次 while 循环没有中断,它处理 xxx2.ts,然后处理 yyy.ts
为什么 HandBrakeCLI 调用会中断我的循环?如何防止它发生?
答案1
while
所写的使用起来并不安全,因为标准输入在进程之间共享,因此HandBrakeCLI
也可能会消耗标准输入。这可以从一个最小的例子中看出:
$ printf "a\nb\nc\n" \
| while IFS= read -r x; do echo $x; sed 's/$/ sed was here/'; done
a
b sed was here
c sed was here
因此,循环会提前退出,因为在涂鸦while
之后,没有其他内容可以从标准输入中读取。sed
解决方法是希望并祈祷代码中没有其他内容正在使用其他文件描述符,例如3
while IFS= read -u 3 -r x; do
echo $x
sed 's/$/ sed read this line/'
done 3< <(printf "a\nb\nc\n")
或切换到不同的编程语言。 (sed
现在将挂起,除非您以某种方式向其提供标准输入。)
另一种选择是关闭程序的标准输入,例如
HandBrakeCLI ... <&-
因为这将阻止它看到循环所需的标准输入while
。