sizeup: tidy filesize information in Terminal

This all started with a simple alias:

alias sizes="du -sh * | sort -n"

That outputs all of the file and folder sizes in the current directory, sorted by size, and lists them in human-readable format. Of course, I wanted to make it a more painful endeavor.

Here’s the result. It’s a shell function that will output the file sizes for files (not folders) and provide a total. It accepts file extensions as arguments, and there are flags for controlling sort order and directory traversal depth. Given the lack of real utility, I won’t go into too much depth, other than to say that the __sizeup_build_query and __sizeup_humanize functions are reusable and pretty handy.

To run in the current folder, just use sizeup. Additional options are:

-r	reverse sort
-[0-3]	limit depth (default 4 levels, 0=unlimited)

arguments limit by file extension

Here’s the code that can be added to or sourced by your .*_profile setup.

__sizeup_build_query () {
	local bool="and"
	local query=""
	for t in $@; do
		query="$query -$bool -iname \"*.$t\""
	echo -n "$query"

__sizeup_humanize () {
	local size=$1
	if [ $size -ge 1073741824 ]; then
		printf '%6.2f%s' $(echo "scale=2;$size/1073741824"| bc) G
	elif [ $size -ge 1048576 ]; then
		printf '%6.2f%s' $(echo "scale=2;$size/1048576"| bc) M
	elif [ $size -ge 1024 ]; then
		printf '%6.2f%s' $(echo "scale=2;$size/1024"| bc) K
		printf '%6.2f%s' ${size} b

sizeup () {
	local helpstring="Show file sizes for all files with totals\n-r\treverse sort\n-[0-3]\tlimit depth (default 4 levels, 0=unlimited)\nAdditional arguments limit by file extension\n\nUsage: sizeup [-r[0123]] ext [,ext]"
	local totalb=0
	local size output reverse OPT
	local depth="-maxdepth 4"
	while getopts "hr0123" opt; do
		case $opt in
			r) reverse="-r " ;;
			0) depth="" ;;
			1) depth="-maxdepth 1" ;;
			2) depth="-maxdepth 2" ;;
			3) depth="-maxdepth 3" ;;
			h) echo -e $helpstring; return;;
			\?) echo "Invalid option: -$OPTARG" >&2; return 1;;
	shift $((OPTIND-1))

	local cmd="find . -type f ${depth}$(__sizeup_build_query $@)"
	local counter=0
	while read -r file; do
		counter=$(( $counter+1 ))
		size=$(stat -f '%z' "$file")
		totalb=$(( $totalb+$size ))
		>&2 echo -ne $'\E[K\e[1;32m'"${counter}:"$'\e[1;31m'" $file "$'\e[0m'"("$'\e[1;31m'$size$'\e[0m'")"$'\r'
		# >&2 echo -n "$(__sizeup_humanize $totalb): $file ($size)"
		# >&2 echo -n $'\r'
		output="${output}${file#*/}*$size*$(__sizeup_humanize $size)\n"
	done < <(eval $cmd)
	>&2 echo -ne $'\r\E[K\e[0m'
	echo -e "$output"| sort -t '*' ${reverse}-nk 2 | cut -d '*' -f 1,3 | column -s '*' -t
	echo $'\e[1;33;40m'"Total: "$'\e[1;32;40m'"$(__sizeup_humanize $totalb)"$'\e[1;33;40m'" in $counter files"$'\e[0m'

Ryan Irelan has produced a series of shell trick videos based on posts. Readers can get 10% off using the coupon code TERPSTRA.

Brett Terpstra

Brett is a writer and developer living in Minnesota, USA. You can follow him as ttscoff on Twitter, GitHub, and Mastodon. Keep up with this blog by subscribing in your favorite news reader.

This content is supported by readers like you.