Skip to content

Instantly share code, notes, and snippets.

@b3niup
Created July 24, 2013 22:33
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save b3niup/6075240 to your computer and use it in GitHub Desktop.
Save b3niup/6075240 to your computer and use it in GitHub Desktop.
#!/bin/bash
### Author: Benedykt 'b3niup' Przybyło
USAGE="Usage: ./$0 [options as for regular cp]"
#*****************************************************************************#
#** Helpers **#
#*****************************************************************************#
function calc {
echo "$1" | bc -l
}
function round {
NUMBER=$1
PREC=$2
if [ -z "$PREC" ]; then PREC=0; fi
PREC=$(( $PREC + 1 ))
if [ ${NUMBER:0:1} = "." ]; then
NUMBER=0$NUMBER
fi
INT=${NUMBER%%\.*}
RES=${NUMBER##*\.}
NUMBER="$INT.${RES:0:$PREC}"
if [ ${NUMBER:(-1)} -ge 5 ]; then
if [ $PREC -eq 1 ]; then
NUMBER=${NUMBER:0:(-2)}
NUMBER=$(( $NUMBER + 1))
else
NUMBER=${NUMBER:0:(-1)}
LAST=${NUMBER:(-1)}
if [ $LAST = "." ]; then
NUMBER=${NUMBER:0:(-1)}
LAST=${NUMBER:(-1)}
fi
NUMBER=${NUMBER:0:(-1)}$(( $LAST + 1 ))
fi
else
if [ $PREC -eq 1 ]; then
NUMBER=${NUMBER:0:(-2)}
else
NUMBER=${NUMBER:0:(-1)}
fi
fi
if [ ${NUMBER:(-1)} = "." ]; then
NUMBER=${NUMBER:0:(-1)}
fi
echo $NUMBER
}
function size_pretty {
# Accepts argument $1 in bytes and returns in human readable format
# $2 is optional decimal places resolution
SIZE=$1
SCALE=$2
UNITS=(B kB MB GB TB PB EB ZB YB)
P=0
if [ -z "$SCALE" ]; then SCALE=2; fi
SCALE=$(( $SCALE + 1 ))
while [ "`calc "$SIZE / 1024 >= 1"`" -eq 1 ]; do
SIZE=`calc "scale=$SCALE; $SIZE / 1024"`
P=$(( $P + 1 ))
done
SIZE=`round $SIZE $SCALE`
echo $SIZE${UNITS[$P]}
}
#*****************************************************************************#
#** Main **#
#*****************************************************************************#
if [ $# -lt 2 ]; then
echo $USAGE
exit 2
elif [ $# -gt 2 ]; then
ARGS=()
for ARG in "$@"; do
if [ ${ARG:0:1} = "-" ]; then
case "$ARG" in
-r|-R|--recursive)
R=1;;
esac
continue
fi
ARGS+=("$ARG")
done
if [ "${#ARGS[@]}" -gt 2 -a -z "$R" ]; then
DIR=${ARGS[$(( ${#ARGS[@]} - 1 ))]}
unset ARGS[$(( ${#ARGS[@]} - 1 ))]
elif [ $R ]; then
DIR=${ARGS[$(( ${#ARGS[@]} - 1 ))]}
unset ARGS[$(( ${#ARGS[@]} - 1 ))]
fi
fi
if [ -d "$1" -a -z "$R" ]; then
echo "Directory $2 has been ommited"
exit 1
fi
if [ "$R" ]; then
if [ ! -d "${ARGS[0]}" ]; then
echo "${ARGS[0]} is not a directory"
exit 1
fi
TSIZE=`du -s "${ARGS[0]}" | cut -f1`
elif [ "$DIR" ]; then
TSIZE=0
for FILE in "${ARGS[@]}"; do
if [ ! -e "$FILE" ]; then
echo "File $FILE does not exist"
exit 1
fi
FSIZE=`du "$FILE" | cut -f1`
if [ $FSIZE ]; then
TSIZE=$(( $TSIZE + $FSIZE ))
fi
done
else
if [ ! -e "$1" ]; then
echo "File $1 does not exist"
exit 1
fi
TSIZE=`du "$1" | cut -f1`
fi
TPSIZE=`size_pretty $(( $TSIZE * 1024 )) 1` #total pretty size
if [ $TSIZE -gt 1048576 ]; then
SLEEP=1
elif [ $TSIZE -gt 102400 ]; then
SLEEP=0.5
else
SLEEP=0.1
fi
cp "$@" &
PID=$!
trap "kill -SIGTERM $PID; exit" SIGINT
trap "kill -SIGTERM $PID; exit" SIGTERM
OLD_WIDTH=`tput cols`
while [ 1 ]; do
if [ -z "$(ps -p $PID | grep $PID)" ]; then
if [ $BREAK ]; then
break
else
BREAK=1
fi
fi
if [ $R ]; then
CSIZE=`du -s "$DIR/${ARGS[0]##*/}" 2> /dev/null | cut -f1`
elif [ "$DIR" ]; then
CSIZE=0
for FILE in "${ARGS[@]}"; do
FSIZE=`du "$DIR/${FILE##*/}" 2> /dev/null | cut -f1`
if [ $FSIZE ]; then
CSIZE=$(( $CSIZE + $FSIZE ))
fi
done
else
if [ -d $2 ]; then
CSIZE=`du "$2/${1##*/}" 2> /dev/null | cut -f1`
else
CSIZE=`du "$2" 2> /dev/null | cut -f1`
fi
fi
WIDTH=`tput cols`
CPSIZE=`size_pretty $(( $CSIZE * 1024 )) 1` #copied pretty size
ILEN=$(( ${#CPSIZE} + 7 + ${#TPSIZE} )) #length of everything except progress bar
PBLEN=$(( $WIDTH - $ILEN )) #progress bar length
PERC=`calc "$CSIZE / $TSIZE * 100"`
PERC=`round $PERC`
PLEN=`calc "$PERC / 100 * $PBLEN"` #progress length
PLEN=`round $PLEN`
echo -en "\r["
for i in `seq 1 $PLEN`; do echo -n "#"; done
for i in `seq 1 $(( $PBLEN - $PLEN ))`; do echo -n "-"; done
echo -n "] $CPSIZE / $TPSIZE "
if [ $OLD_WIDTH -gt $WIDTH ]; then
for i in `seq 1 $(( $OLD_WIDTH - $WIDTH ))`; do echo -n " "; done
fi
OLD_WIDTH=$WIDTH
sleep $SLEEP
done
@ivanalejandro0
Copy link

nice!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment