我想制作一个 shell 脚本,让用户选择已安装的设备并计算该设备上全部数据的校验和。我需要校验和来测试设备是否已被其他人操纵。我的方法如下:
#!/bin/bash
cd "${0%/*}"
device=$(zenity --file-selection --directory \
--filename="/run/media/"${USER}"/"
zenity --info \
--title "Info Message" \
--width 500 \
--height 150 \
--text "$(find "$device" -type f -exec md5sum {} \; | sort -k 2 | md5sum | cut -d ' ' -f 1)"
我的问题是:
- 这是正确的方法吗?
- 如何在设备选择和计算输出对话框之间添加进度条?
答案1
您可以使用pv
它允许您通过管道监视数据的进度。
find "$device" -type f -exec md5sum {} \; | pv -ls $(find "$device" -type f |wc -l) | sort -k 2 | md5sum
-s <size>
提供数据的总大小。由于我们要根据文件数量显示进度,需要知道设备中有多少个文件,因此$(find "$device" -type f |wc -l)
.-l
- 不计算字节数,而是计算行数(换行符)。
第一个find
命令将 md5sum 的结果发送到该pv
命令。pv
将计算完成的百分比(输入行数除以标志提供的总大小-s
),它将向对话框写入终端的标准错误,并将其输入(第一个命令的结果find
)发送到该命令之后的下一个命令管道(在本例中为sort
)。
$ find "$device" -type f -exec md5sum {} \; | pv -ls $(find "$device" -type f |wc -l) | sort -k 2 | md5sum | cut -d ' ' -f 1
6.77k 0:00:10 [1.61k/s] [=========> ] 28% ETA 0:00:24
如果设备上的文件太多,统计文件数量也可能需要很长时间,则可以直接使用pv -l
,此时不会显示完成百分比和预计到达时间,并且进程栏会向左移动并显示正确仅表明数据正在移动。
$ find "$device" -type f -exec md5sum {} \; | pv -l | sort -k 2 | md5sum | cut -d ' ' -f 1
5.64k 0:00:09 [1.72k/s] [ <=> ]
为了在zenity
窗口中显示进度条,您可以执行以下操作:
find "$device" -type f -exec md5sum {} \; \
| ( ( pv -nls $(find "$device" -type f |wc -l) 2>&1 1>&3 ) \
| zenity --progress --auto-close --text="md5sum progress..." 2>/dev/null ) 3>&1 \
| sort -k 2 | md5sum | cut -d ' ' -f 1
-n
flag forpv
- 不会给出进度的视觉指示,而是pv
给出标准错误的整数百分比,每行一个。2>&1
stderr
会将命令的号pv
(百分比计数)重定向到命令的stdout
-号,因此后者可以读取百分比计数并显示进度条。stdin
zenity
1>&3
将旧文件stdout
(命令的输出find ... md5sum
)重定向到新文件描述符 3,以将其与stdin
进程的文件描述符分开zenity
。3>&1
将进程的文件描述符 3pv
(包含命令的输出find
)重定向回stdout
,这是命令stdin
的sort
继续分析。
如果您想md5sum
在另一个zenity
窗口中查看最终输出:
zenity --info \
--title "Info Message" \
--width 500 \
--height 150 \
--text \
"$(find "$device" -type f -exec md5sum {} \; \
| ( ( pv -nls $(find "$device" -type f |wc -l) 2>&1 1>&3 ) \
| zenity --progress --auto-close --text="md5sum progress..." 2>/dev/null ) 3>&1 \
| sort -k 2 | md5sum | cut -d ' ' -f 1)"