How to add a progress bar to a shell script?

后端 未结 30 2280
情歌与酒
情歌与酒 2020-11-22 05:48

When scripting in bash or any other shell in *NIX, while running a command that will take more than a few seconds, a progress bar is needed.

For example, copying a b

30条回答
  •  难免孤独
    2020-11-22 06:36

    I used an answer from Creating string of repeated characters in shell script for char repeating. I have two relatively small bash versions for scripts that need to display progress bar (for example, a loop that goes through many files, but not useful for big tar files or copy operations). The faster one consists of two functions, one to prepare the strings for bar display:

    preparebar() {
    # $1 - bar length
    # $2 - bar char
        barlen=$1
        barspaces=$(printf "%*s" "$1")
        barchars=$(printf "%*s" "$1" | tr ' ' "$2")
    }
    

    and one to display a progress bar:

    progressbar() {
    # $1 - number (-1 for clearing the bar)
    # $2 - max number
        if [ $1 -eq -1 ]; then
            printf "\r  $barspaces\r"
        else
            barch=$(($1*barlen/$2))
            barsp=$((barlen-barch))
            printf "\r[%.${barch}s%.${barsp}s]\r" "$barchars" "$barspaces"
        fi
    }
    

    It could be used as:

    preparebar 50 "#"
    

    which means prepare strings for bar with 50 "#" characters, and after that:

    progressbar 35 80
    

    will display the number of "#" characters that corresponds to 35/80 ratio:

    [#####################                             ]
    

    Be aware that function displays the bar on the same line over and over until you (or some other program) prints a newline. If you put -1 as first parameter, the bar would be erased:

    progressbar -1 80
    

    The slower version is all in one function:

    progressbar() {
    # $1 - number
    # $2 - max number
    # $3 - number of '#' characters
        if [ $1 -eq -1 ]; then
            printf "\r  %*s\r" "$3"
        else
            i=$(($1*$3/$2))
            j=$(($3-i))
            printf "\r[%*s" "$i" | tr ' ' '#'
            printf "%*s]\r" "$j"
        fi
    }
    

    and it can be used as (the same example as above):

    progressbar 35 80 50
    

    If you need progressbar on stderr, just add >&2 at the end of each printf command.

提交回复
热议问题