Page 1 of 2 12 LastLast
Results 1 to 10 of 14

Thread: cp with progress bar in a terminal script

  1. #1
    Join Date
    Dec 2005
    Location
    Paris & Romans-sur-Isère, France -- Singapore
    Beans
    7

    Post cp with progress bar in a terminal script

    Hi all!

    I've just finished writing a small Bash script to watch with a progress gauge the copy of a single file. (name it gcp)

    Use it at your own risk

    See this console extract:

    Code:
    $ gcp pres.tex pres.tex2
    0                                                       100%
    |===========================================================| Done.
    Features:
    • detection of terminal width
    • if second argument is a directory, copies to the directory
    • customization of gauge refresh rate
    • customization of width of gauge


    I leave it here as attachment w/o warranty. Most recent version will be on http://forum.ubuntu-fr.org/viewtopic.php?id=82447.

    Enjoy!

    Benoit

    EDIT. 12.11.2006 - 18.36 protection for file names containing spaces.
    Attached Files Attached Files
    Last edited by pabix; June 29th, 2008 at 03:43 AM.

  2. #2
    Join Date
    Mar 2007
    Location
    TN, US
    Beans
    607
    Distro
    Ubuntu

    Re: cp with progress bar in a terminal script

    How would i edit this for use with the dd command if i wanted to?? Here is the script that I would like to integrate it into if at all possible.....
    Attached Files Attached Files
    Last edited by brennydoogles; August 15th, 2007 at 06:53 PM. Reason: Added more info
    Registered Linux user 446122 , Registered Machine 352936.

  3. #3
    Join Date
    Feb 2009
    Beans
    1

    Re: cp with progress bar in a terminal script

    I can't seem to get the progress bar to run. Any thoughts?

  4. #4
    Join Date
    Mar 2007
    Location
    Australia
    Beans
    38
    Distro
    Ubuntu 7.10 Gutsy Gibbon

    Talking Re: cp with progress bar in a terminal script

    I have made some bugfixes and other alterations.

    Bigfix: Was backspacing the whole line, but when writing the bar, it would only write up to the end of the current progress. Causing it to go back onto previous line in ssh sessions. Solution: write whole line every refresh.

    Optimization: Only update line when there is a change in the number of '=' to write.

    Feature: Returns '1' when an error occurs, '0' normally.


    Surely there must be another way to see if cp is still running other than it looking for that file? can you do it with PIDs?
    Possibly even grep the output of the current processes running to see if its still there.

    Also, there needs to be handling for Control-C, which stops cp.
    Because at the moment, cp still keeps going in the background, even if you Control-C.

    Other than that, Nice script dude

    Code:
    #!/bin/bash
    #                           __    _            __            
    #   ____ __________ _____  / /_  (_)________ _/ /  _________ 
    #  / __ `/ ___/ __ `/ __ \/ __ \/ / ___/ __ `/ /  / ___/ __ \
    # / /_/ / /  / /_/ / /_/ / / / / / /__/ /_/ / /  / /__/ /_/ /
    # \__, /_/   \__,_/ .___/_/ /_/_/\___/\__,_/_/   \___/ .___/ 
    #/____/          /_/                                /_/      
                                            
    # by Pabix (mortgat ... GMAIL ... com)
    
    # BSD License
    #
    # Redistribution and use in source and binary forms, with or
    #   without modification, are permitted provided that the following
    #   conditions are met:
    #
    # *  Redistributions of source code must retain the above
    #    copyright notice, this list of conditions and the following
    #    disclaimer.
    #
    # *  Redistributions in binary form must reproduce the above
    #    copyright notice, this list of conditions and the following
    #    disclaimer in the documentation and/or other materials
    #    provided with the distribution.
    #
    # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
    # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
    # PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR
    # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
    # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
    # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
    # THE POSSIBILITY OF SUCH DAMAGE.
    
    DEBUG=0
    
    #       _       _           _     
    #  __ _| | ___ | |__   __ _| |___ 
    # / _` | |/ _ \| '_ \ / _` | / __|
    #| (_| | | (_) | |_) | (_| | \__ \
    # \__, |_|\___/|_.__/ \__,_|_|___/
    # |___/                           
    
    # Success message
    FINISHED="[Done]"
    
    # Message when copy aborted
    FINISHEDERROR="[Fail]"
    
    # Calculates number of available columns on the terminal
    COLUMNS=$( stty -a | head -n 1 | awk '{print $7}' | rev | cut -b 2- | rev )
    
    # Calculates width of gauge using last value
    COLS=$((${COLUMNS} -${#FINISHED} - 5))
    
    # Default refresh delay
    DELAY=0.1
    
    # Echo ($2), repeated ($1) times
    function multiecho(){
        debug $1 columns times $2
        for i in $(seq 1 $1)
        do
            echo -n -e "$2"
        done
    }
    
    # Display help
    function usage(){
        cat << EOF
        gcp [options] source destination
            copy source file to destination file using a graphical gauge.
                    Only ONE source file is allowed at a time.
    
            options:
    
            -c (n) : use (n) columns to display
            -d     : use debug options
            -h     : display help
            -r (t) : use (t) seconds refresh delay
    EOF
    }
    
    #             _   _                 
    #  ___  _ __ | |_(_) ___  _ __  ___ 
    # / _ \| '_ \| __| |/ _ \| '_ \/ __|
    #| (_) | |_) | |_| | (_) | | | \__ \
    # \___/| .__/ \__|_|\___/|_| |_|___/
    #      |_|                          
    
    # Parsing options
    while getopts "c:dr:h" option
    do
        case $option in
            c)
            COLS=$OPTARG
            ;;
            d)
            DEBUG=1
            ;;
            r)
            DELAY=$OPTARG
            ;;
            h)
            usage
            exit 0
            ;;
            *)
            ;;
        esac
    done
    shift $((OPTIND-1));
    
    # Checks number of options correct
    if [[ $# -ne 2 ]]
    then
        usage
        exit 1
    fi
    
    sourcefile=$1
    if [[ ! -e "$sourcefile" ]]
    then
        usage
        exit 1
    fi
    destinationfile=$2
    
    # Checking that destination is a regular file.
    if [[ -d "$destinationfile" ]]
    then
        destinationfile=${destinationfile%\/}"/"$(basename ${sourcefile})    
    fi
    
    # Warning if destination exists
    if [[ -e "$destinationfile" ]]
    then
        echo WARNING: $destinationfile exists!
    fi
    shift 2
    
    #     _      _                 
    #  __| | ___| |__  _   _  __ _ 
    # / _` |/ _ \ '_ \| | | |/ _` |
    #| (_| |  __/ |_) | |_| | (_| |
    # \__,_|\___|_.__/ \__,_|\__, |
    #                        |___/ 
    
    DEBUGFILE=`tempfile`
    if [[ "$DEBUG" = "1" ]]
    then
        function debug(){
            echo $@ >> $DEBUGFILE
        }
    else
        function debug(){
            :
        }
    fi
    
    debug $COLS columns
    debug source file : $sourcefile
    debug destination : $destinationfile
    
    
    #     _ _           _             
    #  __| (_)___ _ __ | | __ _ _   _ 
    # / _` | / __| '_ \| |/ _` | | | |
    #| (_| | \__ \ |_) | | (_| | |_| |
    # \__,_|_|___/ .__/|_|\__,_|\__, |
    #            |_|            |___/ 
    
    # Backspace
    RET_ARR="\010"
    # sufficient backspacing to go back
    KILLLINE=${RET_ARR}${RET_ARR}
    for i in $(seq 1 $COLS)
    do
        KILLLINE=${KILLLINE}${RET_ARR}
    done
    
    # Rule
    echo -n "0"
    multiecho $(($COLS-4)) " "
    echo '100%' ; 
    
    # Gauge
    echo -n "|"
    multiecho $COLS " "
    echo -n "|"
    
    #                 _       
    # _ __ ___   __ _(_)_ __  
    #| '_ ` _ \ / _` | | '_ \ 
    #| | | | | | (_| | | | | |
    #|_| |_| |_|\__,_|_|_| |_|
    #                         
    
    # Indicator of working cp
    INDFILE=`tempfile`
    
    # Invoking cp
    (nice cp "$sourcefile" "$destinationfile" ; rm $INDFILE) &
    
    # Grabbing source size
    SOURCEFILESIZE=$(($(ls -o "$sourcefile" | awk '{print $4}') + 1))
    DESTFILESIZE=0
    debug source file size : $SOURCEFILESIZE
    LASTPERCENT=0
    
    # MAIN LOOP
    while [[ -e "$INDFILE" ]]
    do
        sleep $DELAY
    
        # Grabbing destination size
        DESTFILESIZE=$(($(ls -o "$destinationfile" | awk '{print $4}') + 1))
        PERCENTAGE=$(($COLS * $DESTFILESIZE / $SOURCEFILESIZE ))
        REST=$(($COLS - $PERCENTAGE))
    
        # Only update when changed
        if [[ $LASTPERCENT -ne $PERCENTAGE ]]
        then
    
            # Displaying gauge
            echo -e -n $KILLLINE"|"
            multiecho $PERCENTAGE "="
            multiecho $REST " "
            echo -n "|"
    
            LASTPERCENT=$PERCENTAGE
        fi
    done
    
    #           _ _   
    #  _____  _(_) |_ 
    # / _ \ \/ / | __|
    #|  __/>  <| | |_ 
    # \___/_/\_\_|\__|
    #                 
    
    # Checks sizes of destination and source
    DESTFILESIZE=$(($(ls -o "$destinationfile" | awk '{print $4}') + 1))
    if [[ "$DESTFILESIZE" != "$SOURCEFILESIZE" ]]
    then
        echo -e "\033[30m!!! $FINISHEDERROR.\033[0m"
    else
        echo " $FINISHED"
    fi
    
    # Debugfile is empty if no debug option specified
    cat $DEBUGFILE
    rm $DEBUGFILE
    
    if [[ "$DESTFILESIZE" != "$SOURCEFILESIZE" ]]
    then
        exit 1
    else
        exit 0
    fi

  5. #5
    Join Date
    Dec 2007
    Beans
    1,045

    Re: cp with progress bar in a terminal script

    thanks for the nice script.

    But if " cp " is running into the backgroup while copying ... that's not so good. I would rather not use it. We shall target a perfect solution.

    There is alternative using rsync. Have you checked in that direction ? with rsync this one ctrl c works


    also:
    http://chris-lamb.co.uk/2008/01/24/c...bar-like-wget/
    Last edited by frenchn00b; January 23rd, 2010 at 07:42 AM.

  6. #6
    Join Date
    Jan 2008
    Beans
    4,757

    Re: cp with progress bar in a terminal script

    Quote Originally Posted by frenchn00b View Post
    thanks for the nice script.

    But if " cp " is running into the backgroup while copying ... That's not so good. I would rather not use it. We shall target a perfect solution.

    There is alternative using rsync. Have you checked in that direction ? With rsync this one ctrl c works


    also:
    http://chris-lamb.co.uk/2008/01/24/c...bar-like-wget/
    +1

  7. #7
    Join Date
    Oct 2005
    Location
    Peru, South America
    Beans
    1,486
    Distro
    Ubuntu 10.10 Maverick Meerkat

    Re: cp with progress bar in a terminal script

    I'm pretty surprised so ingenuitive person hasn't perfected this. Seems like as old as cli is, this would be normal. Apparently it is tougher than it looks. I would love to see something like this.

    Shane

  8. #8
    Join Date
    Aug 2006
    Beans
    31

    Re: cp with progress bar in a terminal script

    Bigfix: Was backspacing the whole line, but when writing the bar, it would only write up to the end of the current progress. Causing it to go back onto previous line in ssh sessions. Solution: write whole line every refresh.
    The problem with this approach is that programs like "watch" will filter out the backspaces, and the result is that you will end up with =s all over the screen.

    This is only important if you're using gcp repeatedly in a script and then "watch"ing it, tho.

  9. #9
    Join Date
    Mar 2010
    Beans
    31

    Re: cp with progress bar in a terminal script

    does anyone have a finished version of this script?i tried to copy and past the new version in a .sh file and added the right permissions,but when click the "run in terminal" ,the terminal window just closes.i also tried to run it from the terminal window,but that didnt work.iam a newb to making scripts,please help.

  10. #10
    Join Date
    Aug 2007
    Beans
    53

    Re: cp with progress bar in a terminal script

    I second the rsync option. For me I just did:
    user@ubuntu:/home/user$ sudo rsync --progress *.avi /home/user2

    And it copies all .avi files from /home/user to /home/user2 (sudo is needed for me since user doesn't have permissions to user2's home directory, it might not be needed in your situation).

    That cp script only does one file at a time, rsync will do multiple files.

Page 1 of 2 12 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •