在 bash 中创建一个进度条

Gha*_*eed 14 command-line 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
Run Code Online (Sandbox Code Playgroud)

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

Mik*_*kel 14

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

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

鞭尾

对话

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

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

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
Run Code Online (Sandbox Code Playgroud)

pv显示通过管道传输的文件或流的进度。然而,它不能(很容易?)用于显示自定义操作(例如循环)的进度。它专为流而设计。

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

一些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
Run Code Online (Sandbox Code Playgroud)

我不知道有任何命令可以提供pv或样式的单行进度条wget,但是有很多简单的 Bash/Perl/sed 脚本可以添加该功能,正如其他人在此处共享的那样。


Byt*_*der 6

您可以使用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
Run Code Online (Sandbox Code Playgroud)

有两种模式:

  • pulsating : 进度条是脉动的,它只是表示有什么东西在运行,但并没有说明任何关于进度的信息。您可以通过设置--pulsating选项来做到这一点。

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

    (echo 10; sleep 2; echo 20; sleep 2; echo 50; sleep 2) | zenity --progress
    
    Run Code Online (Sandbox Code Playgroud)


ins*_*ere 5

这段代码会做到这一点,并且不需要任何东西(当然除了 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
Run Code Online (Sandbox Code Playgroud)

但是,如果您有很多事情要检查,这只会让您的屏幕充满#标志。要解决该问题,请尝试以下代码:

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
Run Code Online (Sandbox Code Playgroud)

将第一行 ( lenProgressBar=5) 中的 5 更改为您希望进度条的长度。打印#长度较短的进度条比长度较长的标志需要更长的时间,但不要让进度条的长度超过您的屏幕尺寸;如果你这样做,它不会很好地工作。(它不会让您使用高于您正在检查的项目数或低于 1 的项目数的进度条)