使 BASH 中的进度条固定在终端底部

Yuk*_*ita 3 command-line bash

我在 BASH 中制作了一个非常基本的进度条,如下所示:-

doned=$1  #amount completed
total=$2  #total amount


doned=`echo $doned $total | awk '{print ($1/$2)}'`
total=`tput cols | awk '{print $1-10}'`
doned=`echo $doned $total | awk '{print int(($1*$2))}'`


echo -n $doned"% [ "

for i in $(seq 1 $doned); do
    echo -n "="
done

for i in $(seq $((doned+1)) $total); do
    echo -n "-"
done

echo " ]"
Run Code Online (Sandbox Code Playgroud)

这完全符合我的要求。

该脚本在另一个脚本的循环中运行。我希望它始终显示在终端的底部或任何其他固定位置。

循环有点像这样:-

for i in 10 20 30 40; do
    echo -n "Do you want to continue on to the next step? (y/n): ";
    read $yn
    if [[ "$yn" == "n" ]] || [[ "$yn" == "N" ]]; then
        exit 1; # stop the script
        d_3=0;
    fi
    doned=`some command` ### Get number of completed files
    totalss=`some other command` ### Get total number of files
    bash ./libraries/prog.sh $doned $totalss
done
Run Code Online (Sandbox Code Playgroud)

所以我想要的是,即使在输入值或显示某些内容时,进度条也会保持在底部。有没有办法做到这一点,最好无需安装任何额外的东西?我想使用此脚本的大多数计算机都是 Debian 8+ 或 Ubuntu 16+ 系统

Yuk*_*ita 5

我编写了一个测试脚本来尝试执行 @MatrixManAtYrService 建议的操作。我意识到这个解决方案并不适用于 U&L SE 涵盖的所有系统,但这在我要求的规范内有效。

#!/bin/bash

# go to last line and print the empty progress bar
tput sc #save the current cursor position
tput cup $((`tput lines`-1)) 3 # go to last line
echo -n "[" # the next 5 lines just print the required stuff to make the bar
for i in $(seq 1 $((`tput cols`-10))); do
    echo -n "-"
done
echo -n "]"
tput rc # bring the cursor back to the last saved position


# the actual loop which does the script's main job
for i in $(seq 0 10 100); do
    # print the filled progress bar
    tput sc  #save the current cursor position
    doned=${i}  #example value for completed amount
    total=100   #example value for total amount

    doned=`echo $doned $total | awk '{print ($1/$2)}'` # the next three lines calculate how many characters to print for the completed amount
    total=`tput cols | awk '{print $1-10}'`
    doned=`echo $doned $total | awk '{print int(($1*$2))}'`


    tput cup $((`tput lines`-1)) 4 #go to the last line
    for l in $(seq 1 $doned); do #this loop prints the required no. of "="s to fill the bar
        echo -n "="
    done
    tput rc #bring the cursor back to the last saved position

    # the next 7 lines are to find the row on which the cursor is currently on to check if it 
    # is at the last line 
    # (based on the accepted answer of this question: /sf/ask/180252621/)
    exec < /dev/tty
    oldstty=$(stty -g)
    stty raw -echo min 0
    tput u7 > /dev/tty
    IFS=';' read -r -d R -a pos
    stty $oldstty
    row=$((${pos[0]:2} - 1))


    # check if the cursor is on the line before the last line, if yes, clear the terminal, 
    # and make the empty bar again and fill it with the required amount of "="s
    if [ $row -gt $((`tput lines`-2)) ]; then
        clear
        tput sc
        tput cup $((`tput lines`-1)) 3
        echo -n "["

        for j in $(seq 1 $((`tput cols`-10))); do
            echo -n "-"
        done
        echo -n "]"
        tput cup $((`tput lines`-1)) 4
        for k in $(seq 1 $doned); do
            echo -n "="
        done
        tput rc
    fi

    # this is just to show that the cursor is behaving correctly
    read -p "Do you want to continue? (y/n)" yn;  

done

 # the next few lines remove the progress bar after the program is over   
tput sc # save the current cursor position
tput cup $((`tput lines`-1)) 3 # go to the line with the progress bar
tput el # clear the current line
tput rc # go back to the saved cursor position
Run Code Online (Sandbox Code Playgroud)

必须有更好的方法来处理溢出到最后一行,而不是清除终端等。这更像是@MatrixManAtYrService 建议的概念证明。欢迎对其限制进行任何改进或评论