如何在输出消息的bash脚本中正确使用tqdm进度条

问题描述 投票:0回答:1

我想知道如何将

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。最后,我将整个循环 + tqdm 复合的 fd 4 重定向到 1 (
4>&1
),以便输出实际上写入 stdout 并打印到终端。

是否有更直接的方法来完成此行为?

bash tqdm
1个回答
0
投票

这里有一种更精致的方法来完成您想要的事情:

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 >/dev/null | tqdm --total 10 --null;
© www.soinside.com 2019 - 2024. All rights reserved.