43

It is really annoying if you adb push/pull large files to the device that there's no way to now how far along it is. Is it possible to run adb push or adb pull and get a progress bar using the 'bar' utility?

The main issue here is I think that adb expects two file names, if the input file could be replaced by stdin you could pipe through the 'bar' utility and get a progress bar. So far I haven't succeeded in doing so, but I'm not really a shell guru which is why I'm asking here :)

Note that I'm on Linux using bash.

N West
  • 6,768
  • 25
  • 40
darkwings
  • 579
  • 1
  • 4
  • 6

4 Answers4

34

It looks like the latest adb has progress support.

Android Debug Bridge version 1.0.32
device commands:
adb push [-p] <local> <remote>
    - copy file/dir to device
    ('-p' to display the transfer progress)

However, the other answers also work for adb install which do not have a progress option. I modified the first answer's script to work this way:

Create adb-install.sh somewhere in your PATH and run adb-install.sh <apk to install> instead of adb install -f <apk to install>

#!/bin/bash
# adb install with progressbar displayed
# usage: <adb-install.sh> <file.apk>
# original code from: http://stackoverflow.com/questions/6595374/adb-push-pull-with-progress-bar

function usage()
{
    echo "$0 <apk to install>"
    exit 1
}

function progressbar()
{
    bar="================================================================================"
    barlength=${#bar}
    n=$(($1*barlength/100))
    printf "\r[%-${barlength}s] %d%%" "${bar:0:n}" "$1"
    # echo -ne "\b$1"
}

export -f progressbar

[[ $# < 1 ]] && usage

SRC=$1

[ ! -f $SRC ] && { \
    echo "source file not found"; \
    exit 2; \
}

which adb >/dev/null 2>&1 || { \
    echo "adb doesn't exist in your path"; \
    exit 3; \
}

SIZE=$(ls -l $SRC | awk '{print $5}')
export ADB_TRACE=all

adb install -r $SRC 2>&1 \
    | sed -n '/DATA/p' \
    | awk -v T=$SIZE 'BEGIN{FS="[=:]"}{t+=$7;system("progressbar " sprintf("%d\n", t/T*100))}'

export ADB_TRACE=

echo

echo 'press any key'
read n
cafce25
  • 15,907
  • 4
  • 25
  • 31
jpage4500
  • 951
  • 9
  • 11
14

Currently I have this little piece of bash:

function adb_push {
  # NOTE: 65544 is the max size adb seems to transfer in one go
  TOTALSIZE=$(ls -Rl "$1" | awk '{ sum += sprintf("%.0f\n", ($5 / 65544)+0.5) } END { print sum }')
  exp=$(($TOTALSIZE * 7)) # 7 bytes for every line we print - not really accurate if there's a lot of small files :(
  # start bar in the background
  ADB_TRACE=adb adb push "$1" "$2" 2>&1 | unbuffer -p awk '/DATA/ { split($3,a,"="); print a[2] }' | unbuffer -p cut -d":" -s -f1 | unbuffer -p bar -of /dev/null -s $exp
  echo  # Add a newline after the progressbar.
}

It works somewhat, it shows a progress bar going from 0 to 100 which is nice. However, it won't be correct if you do a lot of small files, and worse, the bytes/s and total bytes shown by 'bar' aren't correct.

I challenge you to improve on my script; it shouldn't be hard! ;)

Ivan Vučica
  • 9,529
  • 9
  • 60
  • 111
darkwings
  • 579
  • 1
  • 4
  • 6
9

Here is my solution, it will show a simple progressbar and current numeric progress

[==================================================] 100%

Usage

./progress_adb.sh source destination

progress_adb.sh

#!/bin/bash

function usage()
{
    echo "$0 source destination"
    exit 1
}

function progressbar()
{
    bar="=================================================="
    barlength=${#bar}
    n=$(($1*barlength/100))
    printf "\r[%-${barlength}s] %d%%" "${bar:0:n}" "$1"
    # echo -ne "\b$1"
}

export -f progressbar

[[ $# < 2 ]] && usage

SRC=$1
DST=$2

[ ! -f $SRC ] && { \
    echo "source file not found"; \
    exit 2; \
}

which adb >/dev/null 2>&1 || { \
    echo "adb doesn't exist in your path"; \
    exit 3; \
}

SIZE=$(ls -l $SRC | awk '{print $5}')
ADB_TRACE=adb adb push $SRC $DST 2>&1 \
    | sed -n '/DATA/p' \
    | awk -v T=$SIZE 'BEGIN{FS="[=:]"}{t+=$7;system("progressbar " sprintf("%d\n", t/T*100))}'

echo 

Testing on Ubuntu 14.04

$ bash --version
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)

TODO

directory support

progressbar size change when screen size change

Benjamin Loison
  • 3,782
  • 4
  • 16
  • 33
alijandro
  • 11,627
  • 2
  • 58
  • 74
4

Well I can give you an Idea:

ADB_TRACE=adb adb push <source> <destination> 

returns logs for any command, so for example the copy command, which looks like:

writex: fd=3 len=65544: 4441544100000100000000021efd  DATA....#....b..

here you can get the total bytes length before, with ls -a, then parse the output of adb with grep or awk, increment an interneral counter and send the current progress to the bar utility.

When you succeeded, please post the script here.

joecks
  • 4,539
  • 37
  • 48