在本文中,我们将详细介绍如何在Shell脚本中添加进度条。通过计算进度和显示进度条,可以改善用户体验,让用户了解任务的完成情况。
文章目录
进度条是一个图形化的界面元素,它用于表示一个操作的完成进度。它通常由两部分组成:一个表示总进度的背景条,和一个表示当前进度的填充条。填充条的长度相对于背景条的长度表示了操作的完成比例。
在 Shell 脚本中,我们可以使用文本字符来模拟进度条的效果。例如,我们可以使用等号= 来表示填充条,使用空格来表示背景条,然后使用方括号 [] 来包围这些字符,创建出一个文本进度条的效果。以下是一个示例:Progress: [======= ]在这个示例中,进度条的总长度是 10,当前的进度是 7,所以我们使用了 7 个等号和 3 个空格来表示这个进度。
在设计进度条时,我们需要考虑以下几个因素:
echo 和 printf 创建基本进度条,使用 tput 改善进度条的视觉效果,使用 trap 捕获用户中断,或者使用 pv 和 rsync 命令等。echo和[printf](https://www./2021/bash-printf-ming-ling.html "printf")命令来创建一个简单的进度条。以下是一个示例:#!/bin/bash
total=10
for ((i=0;i<=total;i++)); do
printf "\r[%-10s] %d%%" $(repeat '#' $i) $(($i * 10))
sleep 1
done
echo在这个示例中,我们创建了一个总长度为10的进度条。printf命令用于打印进度条,其中%-10s表示进度条的长度,%d%%表示完成的百分比。repeat '#' $i是一个函数,用于重复打印#字符,表示已完成的进度。sleep 1用于模拟工作进度。tput命令可以用于改善终端输出的视觉效果。我们可以使用tput命令来改变进度条的颜色,或者清除进度条。以下是一个示例:#!/bin/bash
total=10
for ((i=0;i<=total;i++)); do
printf "\r\033[0K[%-10s] %d%%" $(repeat '#' $i) $(($i * 10))
sleep 1
done
echo在这个示例中,我们使用了\033[0K来清除当前行的内容,然后再打印新的进度条。这样可以确保进度条在更新时不会出现重叠。[trap](https://www./2023/bash-trap.html "trap")命令来捕获这些中断,并在脚本结束时清理进度条。以下是一个示例:#!/bin/bash
trap 'printf "\n"; stty echo; exit' INT
total=10
for ((i=0;i<=total;i++)); do
printf "\r\033[0K[%-10s] %d%%" $(repeat '#' $i) $(($i * 10))
sleep 1
done
echo在这个示例中,我们添加了一个trap命令,用于捕获INT信号,这个信号通常由用户按下Ctrl+C产生。当捕获到这个信号时,我们打印一个新行,然后退出脚本。这样可以确保即使用户中断脚本的执行,进度条也能被正确的清理。pv 是 "pipe viewer" 的缩写,可以监视通过管道传输数据的进度。如果要传输/压缩/解压缩大文件,可以使用 pv 来显示进度条。例如:pv largefile.tar | tar x在这个示例中,我们使用 pv 来监视 largefile.tar 文件的解压进度。[rsync](https://www./2021/linux-rsync-command.html "rsync")[Shell脚本](/tag/shell "Shell脚本") 提供了内置的进度展示功能,可以使用 --progress 选项来显示文件的同步进度。例如:rsync --progress sourcefile destinationfile在这个示例中,我们使用 rsync 的 --progress 选项来查看 sourcefile 同步到 destinationfile 的进度。printf 命令来输出进度条,然后用 carriage return (\r) 来覆盖同一行的内容,从而创建进度条的动态效果。以下是一个创建自定义进度条的基本示例:
#!/bin/bash
# 定义总的进度
total=100
# 循环,模拟任务进度
for ((i=1;i<=total;i++)); do
# 使用 printf 输出进度条,\r 覆盖同一行内容
printf "\rProgress: [%-100s] %d%%" $(printf '%.0s#' $(seq -s '' $i)) $i
# 模拟任务进度,每次循环 sleep 0.1 秒
sleep 0.1
done
# 输出换行,结束进度条
echo在这个示例中,我们首先定义了一个变量 total 来表示任务的总进度。然后,我们使用一个 for 循环来模拟任务的进度。在每次循环中,我们使用 printf 命令来输出进度条,并使用 \r 来覆盖同一行的内容,从而创建出动态的进度条效果。这个进度条的长度是 100,表示的是任务的完成百分比。我们使用 printf '%.0s#' $(seq -s '' $i) 来输出一个由 # 组成的字符串,字符串的长度等于当前的进度。然后,我们使用 sleep 0.1 来模拟任务的进度。最后,当任务完成时,我们输出一个换行符,以结束进度条。这样,我们就创建了一个简单的自定义进度条。