我想知道如何使用tqdm
除了专用于监视进度的消息之外还打印其他消息的脚本。
例如,假设有一个像这样的循环,其中每个循环周期将三条消息写入 stdout:
for i in $(seq 10);
do
# This is the message used to control progress
echo "progress"
# Other messages, invalidate progess bar
echo "b"
echo "c"
# Simulate work
sleep 0.5
done | tqdm --total 10 --null;
如果执行,此脚本会显示正确的进度条,直到 10 条消息写入 stdout,然后它会返回到最小进度条,就好像没有给出总数一样,如下所示:
30it [00:04, 6.01it/s]
这是因为总数设置为 10,但通过管道发送的消息超过 10 条(实际上是 30 条)。
在 StackOverflow 和 Unix & Linux Stack Exchange 中其他一些帖子的帮助下,我最终写的是这样的内容:
# Based on https://unix.stackexchange.com/a/537435/434897
{
for i in $(seq 10);
do
# This is the message used to control progress. sent to fd 3, only captured by tqdm
echo "progress" >&3
# Other messages, would invalidate progress report if sent directly to tqdm
echo "b"
echo "c"
# Simulate work
sleep 0.1
done 3>&1 >&4 | tqdm --total 10 --null;
} 4>&1
总之,在循环中,我将进度消息写入文件描述符 3 ( echo "progress" >&3
),所有其他消息都写入 stdout。然后,对于循环,我将 3 重定向到 stdout ( 3>&1
),以便可以将这些消息通过管道传输到 tqdm,并将 stdout 重定向到 fd 4 ( >%4
),以避免将其他消息发送到管道和 tqdm。最后,我将4>&1
整个循环 + tqdm 复合的 fd 4 重定向到 1 ( ),以便输出实际上写入 stdout 并打印到终端。
有没有更直接的方法来完成这种行为?