我在 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 " ]"
这完全按照我想要的方式工作。
该脚本在另一个脚本的循环内运行。我希望它始终显示在终端的底部或任何其他固定位置。
循环有点像这样:-
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
所以我想要的是即使在输入值或显示某些内容时进度条仍保持在底部。有没有办法做到这一点,最好不需要安装任何额外的东西?我想使用此脚本的大多数计算机都是 Debian 版本 8+ 或 Ubuntu 16+ 系统
答案1
我编写了一个测试脚本来尝试执行 @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: https://stackoverflow.com/questions/2575037/)
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
必须有更好的方法来处理最后一行的溢出,而不是清除终端等。这更多地是 @MatrixManAtYrService 建议的概念证明。欢迎对其局限性进行任何改进或评论
答案2
答案3
在 shell 脚本中获取进度条的一个简单方法是使用鞭尾或对话框,如评论中所述。大多数 Linux 发行版上都应该提供其中之一或两者。
OP 在评论中提到了 aptitude 安装程序。 Aptitude 是一个使用 ncurses 库的二进制文件,对话框也是如此。