Bash While 循环读取文件在某行退出

Bash While loop read file by line exit on certain line

我正在编写一个简单的 Bash 脚本,它只是调用 HadnBrakeCli 来渲染视频。 我还实现了一个简单的队列选项:队列文件只存储它必须调用以启动渲染的行命令。 所以我写了一个 while 循环来一次读取一行,评估 $line 并重复直到文件结束。

    if [[ ${QUEUE_MODE} = 'RUN' ]]; then
    QUEUE_LEN=`cat ${CONFIG_DIR}/queue | wc -l`
    QUEUE_POS='1'
    printf "Queue lenght:\t ${QUEUE_LEN}\n"

    while IFS= read line; do
        echo "--Running render ${QUEUE_POS} on ${QUEUE_LEN}..."
        echo "++" && echo "$line" && echo "++"
        eval "${line}"
        tail -n +2 "${CONFIG_DIR}/queue" > "${CONFIG_DIR}/queue.tmp" && mv "${CONFIG_DIR}/queue.tmp" "${CONFIG_DIR}/queue"
        echo "--Render ended"
        QUEUE_POS=`expr $QUEUE_POS + 1`
    done < "${CONFIG_DIR}/queue"
    exit 0

问题是任何命令都可以使循环正常工作(空行,回显“测试”...),但是一旦加载了正确的渲染,它就会正确启动和完成,但循环也是如此存在。

我是新手,所以我尝试了一些小改动以查看效果,但结果没有任何改变。 我在 while 循环中注释了命令 tail -n +2 "${CONFIG_DIR}/queue" > "${CONFIG_DIR}/queue.tmp" && mv "${CONFIG_DIR}/queue.tmp" "${CONFIG_DIR}/queue" 或 added/removed IFS= 或删除了 read 命令中的 -r 。 很抱歉,如果这个问题很简单,但我确实遗漏了它如何工作的一些主要部分,所以我什至不知道如何搜索解决方案。

我将在队列文件中放置一个常规渲染示例。 HandBrakeCLI -i "/home/andrea/Videos/done/Rap dottor male e mini me.mp4" -o "/hdd/Render/Output/Rap dottor male e mini me.mkv" -e x265 -q 23 --encoder-preset faster --all-audio -E av_aac -6 dpl2 --all-subtitles -x pmode:pools='16' --verbose=0 2>/dev/null

HandBrakeCLI 从标准输入读取,在 read line 可以看到它之前窃取队列文件的其余部分。我最喜欢的解决方案是通过标准输入以外的方式传递文件,例如文件描述符 #3:

...
while IFS= read line <&3; do    # The <&3 makes it read from FD #3
    ...
done 3< "${CONFIG_DIR}/queue"   # The 3< redirects the file into FD #3

避免该问题的另一种方法是将输入重定向到 HandBrakeCLI 命令:

...
eval "${line}" </dev/null
...

BashFAQ #89: I'm reading a file line by line and running ssh or ffmpeg, only the first line gets processed!

中有更多关于此的信息

此外,我不确定我是否相信您使用 tail 在执行时从队列文件中删除行的方式。我不确定它是否真的 错误 ,它对我来说看起来很脆弱。此外,我建议使用小写或混合大小写的变量名,因为有一堆全大写的名称具有特殊含义,错误地重复使用其中一个可能会产生奇怪的后果。最后,我会通过 shellcheck.net 推荐 运行 您的脚本,因为它会提出一些其他好的建议。

[顺便说一句,这个问题与 "Bash script do loop exiting early" 重复,但没有任何赞成或接受的答案。]