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
...
中有更多关于此的信息
此外,我不确定我是否相信您使用 tail
在执行时从队列文件中删除行的方式。我不确定它是否真的 错误 ,它对我来说看起来很脆弱。此外,我建议使用小写或混合大小写的变量名,因为有一堆全大写的名称具有特殊含义,错误地重复使用其中一个可能会产生奇怪的后果。最后,我会通过 shellcheck.net 推荐 运行 您的脚本,因为它会提出一些其他好的建议。
[顺便说一句,这个问题与 "Bash script do loop exiting early" 重复,但没有任何赞成或接受的答案。]
我正在编写一个简单的 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
...
中有更多关于此的信息
此外,我不确定我是否相信您使用 tail
在执行时从队列文件中删除行的方式。我不确定它是否真的 错误 ,它对我来说看起来很脆弱。此外,我建议使用小写或混合大小写的变量名,因为有一堆全大写的名称具有特殊含义,错误地重复使用其中一个可能会产生奇怪的后果。最后,我会通过 shellcheck.net 推荐 运行 您的脚本,因为它会提出一些其他好的建议。
[顺便说一句,这个问题与 "Bash script do loop exiting early" 重复,但没有任何赞成或接受的答案。]