如何向Zenity进度条发送数值

7
我已经编写了一个简单的脚本,使用7zip备份目录。一切正常,但现在我想添加一些图形反馈,加入进度条。我知道可以使用zenity来实现这一点,但无论我尝试什么,似乎都无法使其工作。
我正在使用fgrep查找何时正在压缩新文件("Compressing"是7zip打印在屏幕上每行的第一个单词),以便增加进度条。具体的代码行如下:
7z a -t7z /home/user/Desktop/Backup.7z /home/user/Desktop/folder_to_backup -mx9 | fgrep Compressing | nl | awk '{print $1/$number_of_files*100}' | zenity --progress --percentage=0 --auto-close

运行这个程序后,进度条出现了,从0开始,但是没有显示进度:当操作完成时,进度条突然跳到了末尾。我已经谷歌搜索了一段时间,但是我只发现zenity progress好像有些问题:D 任何帮助将不胜感激!

运行时会发生什么?我看不出你在使用zenity上有问题。也许问题出在你将什么内容通过管道传递给它了。 - Untitled
@Untitled 你说得对,我忘记加上了,现在我已经更新了我的问题 :) - user1301428
你给zenity什么输入?运行<code>/home/user/Desktop/Backup.7z /home/user/Desktop/folder_to_backup -mx9 | fgrep Compressing | nl | awk '{print $1}'</code>会给你什么结果? - Untitled
@Untitled 的输入是 awk 输出的结果,这是一系列递增的整数(1、2、3……取决于要压缩的文件数量)。如果运行该代码(我刚意识到有个小错误,我忘记添加“7z a -t7z”),则会得到每行一个的“1 2 3”。 - user1301428
[Unix] 进度条。祝好运。 - shellter
请查看我的回答,我更新了它,使其在使用7z压缩时显示进度条。 - user1006989
4个回答

5

看起来你的输出中没有命令的进度,可以尝试在不使用 | zenity --progress --percentage=0 --auto-close 管道的情况下运行你的命令来检查。

可以尝试以下方法获取你的输出,如果你没有安装screen,请先运行 apt-get install screen 安装:

screen -L bash -c '(while :; do tail ~/screenlog.0 | grep -o "[0-9]*%" | tail -1; done | zenity --progress --auto-close &); 7z a "output.zip" "/path/to/input"'

我将解释这个命令的最重要的部分:
  1. screen -L 这个标志告诉 screen 命令启动一个新会话,并将所有终端输出记录到文件中,默认是 ~/screenlog.0
  2. bash -c COMMAND1 生成一个子 shell 并在其中运行 COMMAND1
  3. (COMMAND2 &) 生成另一个子 shell,它将在后台启动 COMMAND2
  4. while :; 开始一个无限循环。
  5. tail FILE 读取文件 FILE 的最后10行。
  6. grep -o 只打印匹配行中匹配到的(非空)部分。
  7. [0-9]*% 匹配任何数字系列,后面跟着百分号。
  8. tail -1 读取上一个管道命令的最后一行。

4

无需创建临时文件的解决方案

终于,在经历了一些头痛和流鼻血之后,我找到了解决方法...

关键在于交互式和非交互式缓冲:

交互式程序通常会对其输出进行行缓冲;即,它们会写出每一行。非交互式程序则会等待直到它们有一个完整的缓冲区,这可能是许多行输出。

现在,如果您将一个非交互式程序管道到另一个程序,则第二个程序在第一个程序写出完整的缓冲区之前不会收到输入。

cd /home/user
export number_of_files=$(find folder_to_backup -type f | wc -l) && ( find folder_to_backup -print0 -type f -exec sh -c "7z a -t7z /path/to/Backup.7z {} -mx9 -bd | grep Compressing" \; | awk -W interactive -v x="$number_of_lines" '{printf "%d\n", (NR*100/x)}' ) | zenity --progress --percentage=0 --auto-close

我可能需要解释一下:

  1. cd /home/user 你需要进入要备份目录的文件夹,否则7z不会在归档中保留目录结构。

  2. export number_of_files=$(find folder_to_backup -type f | wc -l) 首先计算要压缩的文件数量并导出变量以供后续使用。

  3. find folder_to_backup -print0 -type f folder_to_backup 必须是相对路径。(参见1.)

  4. -exec sh -c "7z a -t7z /path/to/Backup.7z {} -mx9 -bd | grep Compressing" \; 对于 find 命令返回的每一行都要启动一个子 shell 并执行带有管道符的 7z 命令和 grep 命令。

  5. awk -W interactive -v x="$number_of_lines" '{printf "%d\n", (NR*100/x)}' 提示 awk 交互 (-W interactive),传递已导出的变量 (-v x="$number_of_lines") 并最终计算并打印百分比 ('{printf "%d\n", (NR*100/x)}')。

  6. 将所有内容置于括号中,并添加 zenity 管道。


1
问题不在于zenity。这是因为7z不会写入stdout。(可能直接处理终端,使用tput或类似命令)。因此,您无法将其管道传输到另一个命令。

如果将命令重定向到文件,则可以看到这一点:

 7z a -t7z /home/user/Desktop/Backup.7z /home/user/Desktop/folder_to_backup -mx9 | fgrep Compressing | nl | awk '{print $1}' > 7z.stdout

在我的7z版本中,文件看起来像这样:

7-Zip [64] 9.20  Copyright (c) 1999-2010 Igor Pavlov  2010-11-18
p7zip Version 9.20 (locale=en_CA.UTF-8,Utf16=on,HugeFiles=on,4 CPUs)

Scanning

Updating archive test.7z

Compressing  test.file

Everything is Ok

这就是为什么我想使用grep生成一些输出并将其管道传输到zenity,我认为这可能会起作用... - user1301428
我的想法是使用类似这样的东西来自己计算百分比:awk '{print $1/$number_of_files*100}' - user1301428
你将要输入什么到$1中?你需要当前文件数量,但是在7z的stdout中没有它。 - Untitled
自从grep按预期工作以来,“压缩”一词出现的次数。 - user1301428
当前文件数量可以计算,所以我拥有所有这些信息。我只是不明白为什么zenity看不到它们。 - user1301428

0
你需要一个子Shell来监视压缩过程,可以通过将文件大小与预期完成大小进行匹配并回显百分比来实现。将该子Shell置于执行压缩的父Shell之中。可以访问http://user.cavenet.com/rolandl并查看ftp-user.txt文件以获取示例。Bash子Shell非常方便!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接