You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

bash/sh/ash中外部程序为何意外干扰while循环的shell变量?

问题:while循环中调用ffmpeg会破坏read读取的变量(隔次迭代出错)

现象复现

在bash、sh或busybox ash的while循环里,用read -rd ''读取空分隔输入时,每次调用ffmpeg后,隔一次迭代就会出现变量损坏——变量开头会缺失几个字节,导致后续命令报错。

复现代码(替换test.mkv为有效视频路径):

#!/bin/bash
while IFS= read -rd '' f;do
    ls -- "$f"
    ffmpeg -i "$f" -c copy -f matroska - &>/dev/null
done < <(printf '%s\0' test.mkv{,,,})

错误输出示例:

test.mkv
ls: cannot access '.mkv': No such file or directory
test.mkv
ls: cannot access 'st.mkv': No such file or directory

无论用进程替换还是外部管道(比如find -print0)传递输入,问题都会出现。

原因

核心问题是ffmpeg默认会读取标准输入(stdin),而while循环里的read正是从这个stdin读取输入数据的。当ffmpeg启动后,它会从stdin读取内容,吃掉了原本要交给下一次read的部分输入,导致read读取到不完整的字符串,最终变量$f损坏。

解决方案

方案1:让ffmpeg不读取stdin

给ffmpeg添加-nostdin参数,强制它不占用标准输入,这样就不会干扰read的读取流程:

#!/bin/bash
while IFS= read -rd '' f;do
    ls -- "$f"
    ffmpeg -nostdin -i "$f" -c copy -f matroska - &>/dev/null
done < <(printf '%s\0' test.mkv{,,,})

方案2:提前读取所有输入到数组

用readarray一次性把所有输入读入数组,再用for循环迭代。这种方法会消耗额外内存,但避免了ffmpeg对stdin的干扰:

#!/bin/bash
readarray -d '' arr < <(printf '%s\0' test.mkv{,,,})
for f in "${arr[@]}";do
    ls -- "$f"
    ffmpeg -i "$f" -c copy -f matroska - &>/dev/null
done

运行后输出正常:

test.mkv
test.mkv
test.mkv
test.mkv

内容的提问来源于stack exchange,提问作者mossymountain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 09:33:31