在bash中创建一个进度条

如何使用bash创建进度条?

这是我的脚本:

#!/bin/bash pass='number1 number12 number13 number14 number15 number16' chk='number14' for i in $pass ; do if [ "$i" == "$chk" ]; then echo ' Found ^_^' else echo 'loading 50%' fi done 

我想用任何东西替换echo 'loading 50%'以创建进度条。

whiptail预装在Ubuntu和许多其他发行版上,并将显示全屏(但仍然是基于终端的)进度元素。

dialogwhiptail的超集,所以这个例子对两者都同样有效。 它确实提供了更高级的UI元素,因此如果您正在寻找文件选择器和表单等用户交互,它可能会派上用场,但它的缺点是不会在许多系统上预装。

鞭尾

对话

 for i in $(seq 1 100) do sleep 0.1 echo $i done | whiptail --title 'Test script' --gauge 'Running...' 6 60 0 

请注意,脚本输出被解释为百分比,因此您可能必须相应地调整输出。

Whiptail和Dialog还允许您通过相当神秘的语法在运行时修改文本:

 phases=( 'Locating Jebediah Kerman...' 'Motivating Kerbals...' 'Treating Kessler Syndrome...' 'Recruiting Kerbals...' ) for i in $(seq 1 100); do sleep 0.1 if [ $i -eq 100 ]; then echo -e "XXX\n100\nDone!\nXXX" elif [ $(($i % 25)) -eq 0 ]; then let "phase = $i / 25" echo -e "XXX\n$i\n${phases[phase]}\nXXX" else echo $i fi done | whiptail --title 'Kerbal Space Program' --gauge "${phases[0]}" 6 60 0 

pv显示通过它传送的文件或流的进度。 然而,它不能(容易地)用于显示诸如循环之类的自定义操作的进度。 它专为流而设计。

 $ head -c 1G < /dev/urandom | pv -s 1G > /dev/null 277MB 0:00:16 [17.4MB/s] [========> ] 27% ETA 0:00:43 

一些真实世界的例子,其中pv派上用场:

 # progress while importing a DB dump pv mybigfile.sql | mysql -uroot -p dbname # importing straight from a remote server ssh user@server 'cat mybigfile.sql.gz' | pv | gzip -cd | mysql -uroot -p dbname # taking a snapshot of a btrfs partition btrfs send /snapshots/$date | pv | btrfs receive /mnt/backup/root 

我不知道任何以pvwget的风格提供单行进度条的命令,但是有很多简单的Bash / Perl / sed脚本会添加该function,正如其他人在这里分享的那样。

您可以使用zenity创建简单的GTK对话框窗口。 其中一个可用选项是进度条对话框。

您可以使用zenity --progress创建这样一个窗口。 为了使它有用,你应该通过添加下面的一些选项来指定更多信息(摘自man zenity ):

  Progress options --text=STRING Set the dialog text --percentage=INT Set initial percentage --auto-close Close dialog when 100% has been reached --auto-kill Kill parent process if cancel button is pressed --pulsate Pulsate progress bar --no-cancel Hides the cancel button 

有两种模式:

  • 脉动 :进度条是脉动的,它只是表明某些东西正在运行,但没有告诉任何进展。 您可以通过设置--pulsating选项来完成此--pulsating

  • manual :您必须将当前进度百分比传递给zenity命令的标准输入以更新进度条。
    这个例子可能如下所示。 请注意,先前的命令被分组到子shell,以便所有输出都重定向到zenity对话框,而不仅仅是最后一个命令:

     (echo 10; sleep 2; echo 20; sleep 2; echo 50; sleep 2) | zenity --progress 

这段代码可以做到,并且不需要任何东西(当然除了bash)。 它打印#符号,就像你在评论中提到的那样:

 pass='number1 number12 number13 number14 number15 number16' chk='number14' passarr=($pass) lenProgressBar=${#passarr[@]} echo -n '[' i=0 while [ $i -lt $lenProgressBar ]; do echo -n '-' ((i++)) done echo -n ']' i=0 while [ $i -lt $lenProgressBar ]; do echo -e -n '\b' ((i++)) done echo -e -n '\b' for i in $pass ; do if [ "$i" = "$chk" ]; then echo -e '#\nFound ^_^' break else echo -n '#' fi done 

但是,如果您有很多需要检查的地方,这只会在屏幕上显示#符号。 要解决该问题,请尝试以下代码:

 lenProgressBar=5 pass='number1 number12 number13 number14 number15 number16' chk='number14' passarr=($pass) lenPass=${#passarr[@]} if [ $lenProgressBar -gt $lenPass ]; then lenProgressBar=lenPass elif [ $lenProgressBar -lt 1 ]; then lenProgressBar=1 fi let "chksForEqualsPrint = $lenPass / $lenProgressBar" echo -n '[' i=0 while [ $i -lt $lenProgressBar ]; do echo -n '-' ((i++)) done echo -n ']' i=0 while [ $i -lt $lenProgressBar ]; do echo -e -n '\b' ((i++)) done echo -e -n '\b' n=1 for i in $pass ; do if [ "$i" = "$chk" ]; then echo -e '\nFound ^_^' break else if [ $n -eq $chksForEqualsPrint ]; then echo -n '#' n=1 else ((n++)) fi fi done 

将第一行中的5( lenProgressBar=5 )更改为您希望进度条的长度。 打印带有较低长度进度条的#符号需要更长的时间,而不是更长的进度条,但不要让进度条的长度超过屏幕尺寸; 如果你这样做,它将无法正常工作。 (它不允许您使用高于您正在检查或低于1的项目数量的进度条)

这是使用ansi转义码的另一种方法:

 #!/bin/bash pass='number1 number2 number 3 number4 number12 number13 number14 number15 number16' chk='number15' result="Not Found!" echo echo -n "Working... " echo -ne "\033[1;32m\033[7m\033[?25l" for i in $pass ; do sleep .4s if [ "$i" == "$chk" ]; then result=" Found ^_^" break else echo -n " " fi done echo -ne "\r\033[0m\033[K\033[?25h" echo $result echo