如何根据可用空间调整进度条的大小?

时间:2011-02-18 17:36:28

标签: bash shell resize progress-bar

我希望得到一个效果,我的进度条的长度相应地调整到我的PuTTY窗口。这个效果是通过wget的进度条完成的。

这是我在bash脚本中使用的程序,用于创建进度条:

_progress_bar

#!/bin/bash

maxwidth=50     # line length (in characters)
filled_char="#"
blank_char="."

current=0 max=0 i=0

current=${1:-0} 
max=${2:-100} 

if (( $current > $max )) 
then 
    echo >&2 "current value must be smaller max. value" 
    exit 1 
fi
percent=`awk 'BEGIN{printf("%5.2f", '$current' / '$max' * 100)}'`

chars=($current*$maxwidth)/$max
echo -ne " ["

while (( $i < $maxwidth )) 
do 
    if (( $i <= $chars ));then
        echo -ne $filled_char 
    else
        echo -ne $blank_char
    fi 
    i=($i+1)
done 

echo -ne "] $percent%\r" 


if (( $current == $max )); then
    echo -ne "\r"
    echo
fi

以下是我如何使用它的示例,此示例查找所有Tor Onion代理退出节点并禁止自定义链下的IP:

#!/bin/bash


IPTABLES_TARGET="DROP"
IPTABLES_CHAINNAME="TOR"

WORKING_DIR="/tmp/"

# get IP address of eth0 network interface
IP_ADDRESS=$(ifconfig eth0 | awk '/inet addr/ {split ($2,A,":"); print A[2]}')



if ! iptables -L "$IPTABLES_CHAINNAME" -n >/dev/null 2>&1 ; then            #If chain doesn't exist
    iptables -N "$IPTABLES_CHAINNAME" >/dev/null 2>&1               #Create it
fi


cd $WORKING_DIR


wget -q -O - http://proxy.org/tor_blacklist.txt -U NoSuchBrowser/1.0 > temp_tor_list1
sed -i 's|RewriteCond %{REMOTE_ADDR} \^||g' temp_tor_list1
sed -i 's|\$.*$||g' temp_tor_list1
sed -i 's|\\||g' temp_tor_list1
sed -i 's|Rewrite.*$||g' temp_tor_list1

wget -q -O - "https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=$IP_ADDRESS&port=80" -U NoSuchBrowser/1.0 > temp_tor_list2
wget -q -O - "https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=$IP_ADDRESS&port=9998" -U NoSuchBrowser/1.0 >> temp_tor_list2
sed -i 's|^#.*$||g' temp_tor_list2



iptables -F "$IPTABLES_CHAINNAME"


CMD=$(cat temp_tor_list1 temp_tor_list2 | uniq | sort)
UBOUND=$(echo "$CMD" | grep -cve '^\s*$')

for IP in $CMD; do
    let COUNT=COUNT+1
    _progress_bar $COUNT $UBOUND
    iptables -A "$IPTABLES_CHAINNAME" -s $IP -j $IPTABLES_TARGET
done

iptables -A "$IPTABLES_CHAINNAME" -j RETURN


rm temp_tor*

编辑:

我意识到第一个示例的人可能不想这样使用,这是一个更简单的概念:

#!/bin/bash

for i in {1..100}; do
    _progress_bar $i 100
done

3 个答案:

答案 0 :(得分:1)

经过一些谷歌搜索后,我发现了以下内容:

tput cols将返回列数,就像Sdaz建议的COLUMNS var。

因此我会: maxwidth=$(tput cols)除非其他人采用更加防弹的方式而不需要tput

答案 1 :(得分:1)

我对您的脚本进行了一些更改:

  • 将其转换为函数。如果要将其保存在单独的文件中,以便可以使用多个脚本,只需在每个脚本中获取文件即可。这样做可以消除重复调用外部脚本的开销。
  • 消除了while循环(无论如何应该是for ((i=0; $i < $maxwidth; i++))循环),以便大幅提升速度。
  • 更改了算术表达式,以便他们立即进行评估,而不是将它们设置为字符串以供日后评估。
  • 从变量名中删除美元符号,它们出现在算术上下文中。
  • echo -en更改为printf
  • 进行了一些其他更改
  • 更改了AWK输出,因此“100.00%”与较小的值进行十进制对齐。
  • 更改了AWK命令以使用变量传递而不是“inside-out:quoting。

结果如下:

_progress_bar () {
    local maxwidth=50     # line length (in characters)
    local filled_char="#"
    local blank_char="."

    local current=0 max=0 i=0
    local complete remain

    current=${1:-0}
    max=${2:-100}

    if (( current > max ))
    then
        echo >&2 "current value must be smaller than max. value"
        return 1
    fi
    percent=$(awk -v "c=$current" -v "m=$max" 'BEGIN{printf("%6.2f", c / m * 100)}')

    (( chars = current * maxwidth / max))

    # sprintf n zeros into the var named as the arg to -v
    printf -v complete '%0*.*d' '' "$chars" ''
    printf -v remain '%0*.*d' '' "$((maxwidth - chars))" ''

    # replace the zeros with the desired char
    complete=${complete//0/"$filled_char"}
    remain=${remain//0/"$blank_char"}

    printf ' [%s%s] %s%%\r' "$complete" "$remain" "$percent"
}

问题是什么?哦,见BashFAQ/091。使用tputbash -i$COLUMNS。但是,如果您使用bash -i,请注意它将具有处理启动文件的开销

答案 2 :(得分:0)

Bash分别将LINESCOLUMNS envvars导出到窗口行和列计数。此外,当您通过SSH或telnet协议调整putty窗口的大小时,协议中有足够的逻辑将WINCH信号发送到活动shell,然后将这些值重置为新的窗口维度。

在bash脚本中,使用COLUMNS变量设置当前尺寸,然后除100 / progbarlen(基于COLUMNS变量的一部分的progbarlen)以获得构成一个字符的百分点数,随着你的进步而前进。要动态处理调整大小,请为SIGWINCH添加处理程序(通过trap)并重新读取COLUMNS envvar,然后使用新维度重新绘制进度条。

(我没有在shell脚本中对此进行测试,并且可能需要一些额外的逻辑,但这是bash检测/处理调整大小的方式。)