into
我正在使用管道中的pv
命令来显示进度栏。我尝试了一个简单的计数器:
for (( i = 1 ; i <= 100 ; i++ )); do sleep 1; echo $i; done | pv --progress --line-mode --size 100 --eta --timer
这可以正常工作,但是我希望进度栏在同一行上显示。此答案解释了如何做到这一点。
所以我尝试了:
for (( i = 1 ; i <= 100 ; i++ )); do sleep 1; echo $i; done | >&2 echo -en "r"; pv --progress --line-mode --size 100 --eta --timer
它停留在一行上,但现在不再更新ETA。
问题
我如何也可以更新ETA?
更新
现在,Ibug回答了上一节中的问题,我意识到我还有一个相关的要求:需要保留stdout
,因此可以在下一个管道中使用。在我的具体情况下,我需要将结果写入文件(即> some-file.txt
)
您正在输入错误的命令。
for (( i = 1 ; i <= 100 ; i++ )); do sleep 1; echo $i; done | >&2 echo -en "r"; pv --progress --line-mode --size 100 --eta --timer
^
pv
之前有一个半龙,因此您实际上是在stdin/stdout上运行的,这是您的终端。您应该对额外的echo
和pv
进行分组,以使其从for
循环中读取:
for (( i = 1 ; i <= 100 ; i++ )); do sleep 1; echo $i; done | (>&2 echo -en "r"; pv --progress --line-mode --size 100 --eta --timer)
为什么第一个命令不是这种情况?这是因为整个for do done
子句被视为一个命令,因此其结果正确地将其管道输送到pv
。但是,在第二个命令中,结果将管道输送到echo
。您知道,echo
没有从stdin中读取任何内容。
由于pv
将STDIN引导到Stdout,因此数字也将输出输出到终端,该终端与STDERR的指示混合在一起。要抑制非输出输出,请将其重定向到/dev/null
,因此最终命令为
for (( i = 1 ; i <= 100 ; i++ )); do sleep 1; echo $i; done | (>&2 echo -en "r"; pv --progress --line-mode --size 100 --eta --timer) > /dev/null
如果要将输出重定向到文件,只需在命令末尾更改/dev/null
。