How to add a progress bar to a shell script?

后端 未结 30 2218
情歌与酒
情歌与酒 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:22

    GNU tar has a useful option which gives a functionality of a simple progress bar.

    (...) Another available checkpoint action is ‘dot’ (or ‘.’). It instructs tar to print a single dot on the standard listing stream, e.g.:

    $ tar -c --checkpoint=1000 --checkpoint-action=dot /var
    ...
    

    The same effect may be obtained by:

    $ tar -c --checkpoint=.1000 /var
    
    0 讨论(0)
  • 2020-11-22 06:25

    Some posts have showed how to display the command's progress. In order to calculate it, you'll need to see how much you've progressed. On BSD systems some commands, such as dd(1), accept a SIGINFO signal, and will report their progress. On Linux systems some commands will respond similarly to SIGUSR1. If this facility is available, you can pipe your input through dd to monitor the number of bytes processed.

    Alternatively, you can use lsof to obtain the offset of the file's read pointer, and thereby calculate the progress. I've written a command, named pmonitor, that displays the progress of processing a specified process or file. With it you can do things, such as the following.

    $ pmonitor -c gzip
    /home/dds/data/mysql-2015-04-01.sql.gz 58.06%
    

    An earlier version of Linux and FreeBSD shell scripts appears on my blog.

    0 讨论(0)
  • I have built on the answer provided by fearside

    This connects to an Oracle database to retrieve the progress of an RMAN restore.

    #!/bin/bash
    
     # 1. Create ProgressBar function
     # 1.1 Input is currentState($1) and totalState($2)
     function ProgressBar {
     # Process data
    let _progress=(${1}*100/${2}*100)/100
    let _done=(${_progress}*4)/10
    let _left=40-$_done
    # Build progressbar string lengths
    _fill=$(printf "%${_done}s")
    _empty=$(printf "%${_left}s")
    
    # 1.2 Build progressbar strings and print the ProgressBar line
    # 1.2.1 Output example:
    # 1.2.1.1 Progress : [########################################] 100%
    printf "\rProgress : [${_fill// /#}${_empty// /-}] ${_progress}%%"
    
    }
    
    function rman_check {
    sqlplus -s / as sysdba <<EOF
    set heading off
    set feedback off
    select
    round((sofar/totalwork) * 100,0) pct_done
    from
    v\$session_longops
    where
    totalwork > sofar
    AND
    opname NOT LIKE '%aggregate%'
    AND
    opname like 'RMAN%';
    exit
    EOF
    }
    
    # Variables
    _start=1
    
    # This accounts as the "totalState" variable for the ProgressBar function
    _end=100
    
    _rman_progress=$(rman_check)
    #echo ${_rman_progress}
    
    # Proof of concept
    #for number in $(seq ${_start} ${_end})
    
    while [ ${_rman_progress} -lt 100 ]
    do
    
    for number in _rman_progress
    do
    sleep 10
    ProgressBar ${number} ${_end}
    done
    
    _rman_progress=$(rman_check)
    
    done
    printf '\nFinished!\n'
    
    0 讨论(0)
  • 2020-11-22 06:26

    Got an easy progress bar function that i wrote the other day:

    #!/bin/bash
    # 1. Create ProgressBar function
    # 1.1 Input is currentState($1) and totalState($2)
    function ProgressBar {
    # Process data
        let _progress=(${1}*100/${2}*100)/100
        let _done=(${_progress}*4)/10
        let _left=40-$_done
    # Build progressbar string lengths
        _fill=$(printf "%${_done}s")
        _empty=$(printf "%${_left}s")
    
    # 1.2 Build progressbar strings and print the ProgressBar line
    # 1.2.1 Output example:                           
    # 1.2.1.1 Progress : [########################################] 100%
    printf "\rProgress : [${_fill// /#}${_empty// /-}] ${_progress}%%"
    
    }
    
    # Variables
    _start=1
    
    # This accounts as the "totalState" variable for the ProgressBar function
    _end=100
    
    # Proof of concept
    for number in $(seq ${_start} ${_end})
    do
        sleep 0.1
        ProgressBar ${number} ${_end}
    done
    printf '\nFinished!\n'
    

    Or snag it from,
    https://github.com/fearside/ProgressBar/

    0 讨论(0)
  • 2020-11-22 06:28

    I would also like to contribute my own progress bar

    It achieves sub-character precision by using Half unicode blocks

    Code is included

    0 讨论(0)
  • 2020-11-22 06:28

    My solution displays the percentage of the tarball that is currently being uncompressed and written. I use this when writing out 2GB root filesystem images. You really need a progress bar for these things. What I do is use gzip --list to get the total uncompressed size of the tarball. From that I calculate the blocking-factor needed to divide the file into 100 parts. Finally, I print a checkpoint message for each block. For a 2GB file this gives about 10MB a block. If that is too big then you can divide the BLOCKING_FACTOR by 10 or 100, but then it's harder to print pretty output in terms of a percentage.

    Assuming you are using Bash then you can use the following shell function

    untar_progress () 
    { 
      TARBALL=$1
      BLOCKING_FACTOR=$(gzip --list ${TARBALL} |
        perl -MPOSIX -ane '$.==2 && print ceil $F[1]/50688')
      tar --blocking-factor=${BLOCKING_FACTOR} --checkpoint=1 \
        --checkpoint-action='ttyout=Wrote %u%  \r' -zxf ${TARBALL}
    }
    
    0 讨论(0)
提交回复
热议问题