我用来tar
快速复制数千个小文件,通过管道pv
显示复制的进度和速度。
$ sudo tar c --files-from /tmp/camfilenames |
pv --width 40 |
sudo tar x -C /home/pi/test
...这工作得很好。输出示例:
191MiB 0:00:03 [58.1MiB/s] [<=> ]
...在航站楼。但我想用这个输出做更多的事情,我有简单的 python 脚本/home/pi/screentest.py
:
import sys
print "start"
for line in sys.stdin:
print "line: " + line
print "end"
测试运行:
$ ( sudo tar c --files-from /tmp/camfilenames |
pv --width 40 |
sudo tar x -C /home/pi/test ) |
python /home/pi/screentest.py
输出:
start
191MiB 0:00:03 [55.1MiB/s] [<=> ]
end
我知道pv
返回一个缓冲区中的所有内容,那么如何强制它逐行返回并每次刷新缓冲区以输出类似以下内容:
start
line: 0MiB 0:00:00 ...
line: 60MiB 0:00:01 ...
line: 120MiB 0:00:02 ...
line: 191MiB 0:00:03 ...
end
答案1
pv
将进度输出到 stderr,因此管道到 python 脚本没有从pv
.它在输出停止end
后打印,可能是因为那时最后一个输出已经退出,因此脚本的标准输入已经关闭。pv
tar
您可能需要类似的东西:
( sudo tar c --files-from /tmp/camfilenames |
pv --width 40 -f |
sudo tar x -C /home/pi/test ) 2>&1 >/dev/null | python /home/pi/screentest.py
我们丢弃 tar 管道的 stdout,而是将 stderr 发送到 pythons 脚本。请注意,我们需要强制pv
with输出进度-f
,因为pv
如果 stderr 不是终端,则不会进度。
但您可能想查看 topv
的--format
选项。你可以使用类似的东西:
sudo tar c --files-from /tmp/camfilenames |
pv --width 40 --format $'%b %t\n' |
sudo tar x -C /home/pi/test
以获得类似的输出。
答案2
谢谢@muru,我尝试了你的解决方案,但与此同时,我发现主要问题是强制 PV 输出新行,而不是不断更新一行。
所以我写了这个:
$ tail -f /home/pi/log | pv -f |& stdbuf -oL tr '\r' '\n'
它起作用了,所以现在的问题是 - 如何调用我的 python 脚本来对每一行执行某些操作 - 我发现我可以使用 do-while 循环来实现这一点:
$ tail -f /home/pi/log | pv -f |& stdbuf -oL tr '\r' '\n' | (while read -r LINE; do echo $LINE; done;)
因此,有了这个,我只需使用我的 python 脚本(小 LCD 处理程序)在 LCD 上显示 PV 状态:
tail -f /home/pi/log | pv -f --width 20 -i 2 |& stdbuf -oL tr '\r' '\n' | (while read -r LINE; do python /home/pi/screen.py $LINE; done;)
我重新引入了我的 TAR 脚本,将许多小文件复制到其中:
$ (sudo tar c --files-from /tmp/camfilenames | pv -f --width 20 -i 1 | sudo tar x -C /home/pi/test) |& stdbuf -oL tr '\r' '\n' | (while read -r LINE; do python /home/pi/screen.py $LINE; done;)
所以最后,当我向 PV 添加更多参数,并且在将 PV 输出发送到 LCD 之前我做了一些字符串替换,并且添加了一些断行时,我有以下内容:
cd /home/pi/cam \ && ( \ sudo tar c --files-from /tmp/camfilenames \ | pv -f -s $( \ du -sb /home/pi/cam \ | awk '{print $1}' \ ) --width 64 -i 5 \ | sudo tar x -C /mnt/usb \ ) \ |& stdbuf -oL tr '\r' '\n' \ | ( \ while read -r LINE; \ do LINE="${LINE// /_}"; \ LINE="${LINE//_\[/ [}"; \ LINE="${LINE//\]_/] }"; \ lcd $LINE; \ done; \ ) \ && cd /home/pi