Files
q-tools/files/fastdu
ville rantanen 5c2c1c39a1 fix docs
2019-07-14 12:15:42 +03:00

136 lines
3.4 KiB
Bash
Executable File

#!/bin/bash
function helpexit() {
echo "Display file/folder sizes like 'du', but faster and actual byte sizes"
echo "Returns only the size as number"
echo " -h Human readable units"
echo " -s Summary mode, otherwise each argument folder calculated separate"
echo " -c Count files in addition of summarizing sizes"
echo " -a Display animation while counting"
echo " -f # Format filesize to human readable. Command exits without scanning."
echo " --help This help"
exit
}
function filesize() {
# Return a human readable size from integer of bytes
# Usage: filesize 10000
[ "$1" = "0" ] && {
echo "0~B"
return 0
}
awk 'BEGIN{ x = '$1'
split("B kB MB GB TB PB EB ZB", type)
for(i=7;y < 1;i--)
y = x / (2^(10*i))
if (i==-1) { printf( "%d~B", x) }
if (i>-1) { printf( "%0.1f%s", y, type[i+2]) }
}' || return $?
}
function siprefix() {
# Return a SI prefixed string from integer
[ "$1" = "0" ] && {
echo "0~#"
return 0
}
awk 'BEGIN{ x = '$1'
split("# k# M# G# T# P# E# Z#",type)
for(i=7;y < 1;i--)
y = x / (10^(3*i))
if (i==-1) { printf( "%d~#", x) }
if (i>-1) { printf( "%0.1f%s", y, type[i+2]) }
}' || return $?
}
function animate() {
CHARS=( "| " "/ " " _ " " \\" " |" " \\" " _ " "/ " )
i=0
while true; do
sleep 0.2
printf "\r %s\r" "${CHARS[$i]}" >&2
i=$(( (i + 1)%${#CHARS[@]} ))
done
}
function processfolder() {
SIZECOUNT=( $( find "$@" -type f -printf %s"\n" 2>/dev/null | awk '{ sum += $1; count += 1 } END { print int(sum)+0 , int(count)+0 }' ) )
SIZE=${SIZECOUNT[0]}
[[ "$HUMAN" -eq 1 ]] && {
SIZE=$( filesize "$SIZE" )
}
[[ "$COUNT" -eq 1 ]] && {
COUNTS=${SIZECOUNT[1]}
[[ "$HUMAN" -eq 1 ]] && {
COUNTS=$( siprefix "$COUNTS" )
}
}
echo -e "$SIZE\t$COUNTS"
}
function formatter() {
cat - | xargs printf "$FORMAT" | sed -e 's,~B, B,' -e 's,~#, #,'
}
# Get options
what=()
for (( i=1; i<=$#; i++ )); do
[[ "${!i}" = "-f" ]] && { FORMAT=1; ((i++)); FORMAT_VALUE=${!i}; continue; }
[[ "${!i}" = "--help" ]] && helpexit
[[ "${!i}" = "-"* ]] && {
[[ "${!i}" =~ -.*a ]] && { ANIMATE=1; }
[[ "${!i}" =~ -.*h ]] && { HUMAN=1; }
[[ "${!i}" =~ -.*c ]] && { COUNT=1; }
[[ "${!i}" =~ -.*s ]] && { SUMMARY=1; }
continue
}
what+=( "${!i}" )
done
[[ -z "${what[@]}" ]] && what="."
# If formatting requested, do only that:
if [[ "$FORMAT" -eq 1 ]]; then
if [[ -z "$FORMAT_VALUE" ]]; then
echo -e "\nBytes argument missing\n\n"
helpexit
fi
filesize $FORMAT_VALUE | sed 's,~B, B,'
exit $?
fi
# If only one entry, dont print the name
[[ "${#what[@]}" -eq 1 ]] && SUMMARY=1
if [[ "$ANIMATE" -eq 1 ]]; then
trap 'trap - SIGTERM && kill -- -$$' EXIT SIGINT SIGTERM
animate &
fi
[[ "$HUMAN" -eq 1 ]] && NUMFORMAT="%7s "
[[ "$HUMAN" -ne 1 ]] && NUMFORMAT="%d\t"
[[ "$COUNT" -eq 1 ]] && NUMBERS="$NUMFORMAT$NUMFORMAT"
[[ "$COUNT" -ne 1 ]] && NUMBERS="$NUMFORMAT"
[[ "SUMMARY" -eq 1 ]] && FORMAT="$NUMBERS\n"
[[ "SUMMARY" -ne 1 ]] && FORMAT="$NUMBERS"
if [[ "$SUMMARY" -eq 1 ]]; then
# Display one line
processfolder "${what[@]}" | formatter
else
# One size for each argument
for ((i=0; i<"${#what[@]}"; i++)); do
processfolder "${what[$i]}" | formatter
echo "${what[$i]}"
done
fi
if [[ "$ANIMATE" -eq 1 ]]; then
trap - EXIT SIGINT SIGTERM
kill %1
fi