-
-
Save eguven/23d8c9fc78856bd20f65f8bcf03e691b to your computer and use it in GitHub Desktop.
# this original one uses values returned from 'brew info' | |
brew list --formula | xargs -n1 -P8 -I {} \ | |
sh -c "brew info {} | egrep '[0-9]* files, ' | sed 's/^.*[0-9]* files, \(.*\)).*$/{} \1/'" | \ | |
sort -h -r -k2 - | column -t | |
# faster alternative using 'du' | |
du -sch $(brew --cellar)/*/* | sed "s|$(brew --cellar)/\([^/]*\)/.*|\1|" | sort -k1h |
Alternative: brew install ncdu && ncdu /opt/homebrew/Cellar
Works on fish
shell without parallel
:
brew list --formula | xargs -P8 -I {} sh -c "brew info {} | grep -E '\([0-9]+ files'" \
| awk -F '[/(),]' '{print $6 ", " $8 ", " $9}' | sort -t "," -rh -k3
and gives output in a comma-separated format which can be simply changed in the awk command:
exiftool, 603 files, 25.3MB
micro, 7 files, 11.4MB
tealdeer, 12 files, 5.4MB
bat, 14 files, 4.6MB
eza, 14 files, 1.1MB
Worked for me too! Thanks!
TLDR; the du-wildcard
version is the simplest and fastest.
du -sch $(brew --cellar)/*/* | sort -k1h
Summary of pipelines and timings
alias | description (summary of pipeline) | runtime (sec) |
---|---|---|
parallel | brew list | parallel "brew info {}" |
60.6667 avg |
linear | brew info $(brew list) |
25.333 avg |
du-formula | brew list | xargs brew --cellar | xargs du -sch |
3.4 |
du-version | brew_list_with_versions | xargs du -sch |
2.5 |
du-wildcard | du -sch $(brew --cellar)/*/* |
0.4 |
Three run average, for parallel
and linear
parallel | linear | |
---|---|---|
t1 | 61 | 25 |
t2 | 61 | 25 |
t3 | 60 | 26 |
avg | 60.6667 | 25.333 |
Let's go over the existing solutions from above.
First, lets wrap our brew info ... | sed ...
pipeline into a function.
Also note, that all lsited functions here are bash
and zsh
compatible.
# simplify this:
# egrep '[0-9]* files, ' | sed 's/^.*[0-9]* files, \(.*\)).*$/{} \1/'
# into this:
# sed -nE -e '/[0-9]+ files, /{s,.*/Cellar/,,;s/ \(.* files, ([^)]+)\)/ \1/p}'
# and, allow multiple args for 'brew info'
brew_formula_size() {
brew info "${@?}" \
| sed -nE -e '
/[0-9]+ files, /{
s,.*/Cellar/,,
s/ \(.* files, ([^)]+)\)/ \1/p
}'
}
And, then, lets wrap the sizing into a parallel pipeline function
brew_sizes() {
if [ $# -gt 0 ]; then
printf '%s\n' "$@"
else
brew list --formula
fi \
| parallel "bash -c 'brew_formula_size {}'" \
| sort -k2h
}
# Example usages using gnu parallel:
brew_sizes zlib util-linux | column -t
brew_sizes | tail | column -t
However, parallel fs sizing operations won't improve performance. Here's the timing for the parallel
version.
$ time { brew_sizes | tail | column -t; }
Warning: Formula pev was renamed to readpe.
icu4c/74.2 85.0MB *
berkeley-db@5/5.3.28_1 87.7MB
ghostscript/10.03.0 170.7MB *
boost/1.85.0 226.9MB *
go/1.22.3 259.5MB *
gcc/14.1.0 359.7MB *
binutils/2.42 490.5MB
mingw-w64@11.0.1/11.0.1 1GB
mingw-w64/11.0.1_1 1GB *
llvm/18.1.5 2.7GB
real 0m59.004s
user 5m12.727s
sys 1m30.422s
Since brew info
accepts multiple formulas, we can do a linear, non-parallel version.
# Example usages, linear non-parallel:
brew_formula_size zlib util-linux | column -t
brew_formula_size $(brew list --formula) | sort -k2h | tail | column -t
$ time { brew_formula_size $(brew list --formula) | sort -k2h | tail | column -t; }
Warning: Formula pev was renamed to readpe.
icu4c/74.2 85.0MB *
berkeley-db@5/5.3.28_1 87.7MB
ghostscript/10.03.0 170.7MB *
boost/1.85.0 226.9MB *
go/1.22.3 259.5MB *
gcc/14.1.0 359.7MB *
binutils/2.42 490.5MB
mingw-w64@11.0.1/11.0.1 1GB
mingw-w64/11.0.1_1 1GB *
llvm/18.1.5 2.7GB
real 0m25.452s
user 0m11.543s
sys 0m6.668s
You could just pipe everything to du
and get the sizes per formula, but not the sizes per formula per version.
# one-liners, using 'du', but does not show sizes per installed version
printf '%s\n' zlib util-linux | xargs brew --cellar | xargs du -sch | sort -k1h
brew list --formula | xargs brew --cellar | xargs du -sch | sort -k1h | tail
$ time { brew list --formula | xargs brew --cellar | xargs du -sch | sort -k1h | tail; }
Warning: Formula pev was renamed to readpe.
123M /home/linuxbrew/.linuxbrew/Cellar/ruby
172M /home/linuxbrew/.linuxbrew/Cellar/ghostscript
263M /home/linuxbrew/.linuxbrew/Cellar/boost
295M /home/linuxbrew/.linuxbrew/Cellar/go
363M /home/linuxbrew/.linuxbrew/Cellar/gcc
502M /home/linuxbrew/.linuxbrew/Cellar/binutils
1.1G /home/linuxbrew/.linuxbrew/Cellar/mingw-w64
1.1G /home/linuxbrew/.linuxbrew/Cellar/mingw-w64@11.0.1
2.8G /home/linuxbrew/.linuxbrew/Cellar/llvm
8.1G total
real 0m3.378s
user 0m1.879s
sys 0m0.999s
brew list --formula --versions
does produce all the versions for each formula.
$ brew list --formula --versions zlib util-linux
util-linux 2.40.1 2.39.3
zlib 1.3.1
You could then fold the formulas together with the versions, like this:
# array slicing, like ${arr[@]:start} and ${arr[@]:start:length}
# works in bash and zsh,
# and 'start' starts at 0, for both bash and zsh
#
# for input 'foo 1.2 3.4' into 'read -a form',
# ${form[@]:0:1} == 'foo'
# ${form[@]:1} == (1.2 3.4) # sub-array
#
# $ printf '%s\n' arg1 arg2
# arg1
# arg2
# ^-- printf will repeat the format pattern for each arg
# "${array[@]}" will turn into multiple args, if non-empty
#
brew_list_with_versions() {
brew list --formula --versions "$@" \
| while read -a form; do
printf "$(brew --cellar)/${form[@]:0:1}/%s\n" "${form[@]:1}"
done
}
$ brew_list_with_versions zlib util-linux
/home/linuxbrew/.linuxbrew/Cellar/util-linux/2.40.1
/home/linuxbrew/.linuxbrew/Cellar/util-linux/2.39.3
/home/linuxbrew/.linuxbrew/Cellar/zlib/1.3.1
# one-liners, using 'du', show sizes per formula per installed version
brew_list_with_versions zlib util-linux | xargs du -sch | sort -k1h
brew_list_with_versions | xargs du -sch | sort -k1h | tail
# NOTE: this was run after the above timed pipeline, which showed 'real 0m3.378s'
$ time { brew_list_with_versions | xargs du -sch | sort -k1h | tail; }
123M /home/linuxbrew/.linuxbrew/Cellar/ruby/3.3.1
172M /home/linuxbrew/.linuxbrew/Cellar/ghostscript/10.03.0
263M /home/linuxbrew/.linuxbrew/Cellar/boost/1.85.0
295M /home/linuxbrew/.linuxbrew/Cellar/go/1.22.3
363M /home/linuxbrew/.linuxbrew/Cellar/gcc/14.1.0
502M /home/linuxbrew/.linuxbrew/Cellar/binutils/2.42
1.1G /home/linuxbrew/.linuxbrew/Cellar/mingw-w64/11.0.1_1
1.1G /home/linuxbrew/.linuxbrew/Cellar/mingw-w64@11.0.1/11.0.1
2.8G /home/linuxbrew/.linuxbrew/Cellar/llvm/18.1.5
8.1G total
real 0m2.465s
user 0m1.071s
sys 0m1.410s
You could just use 'du' on Cellar/some_formula/some.version
like this:
du -sch $(brew --cellar)/*/* | sort -k1h | tail
du -sch $(brew --cellar)/{zlib,util-linux}/* | sort -k1h
# pipeline version for specific formulas,
# 'paste -sd,' joins input lines with comma
echo zlib util-linux | bash -c "du -sch $(brew --cellar)/{$(xargs -n1|paste -sd,)}/*"
echo zlib util-linux | xargs -n1 | paste -sd, | bash -c "du -sch $(brew --cellar)/{$(cat)}/*"
du_wildcard() {
typeset forms=$(tty --quiet || xargs --no-run-if-empty -n1 | paste -sd,)
if [ x"${forms}" = x ]; then
du -sch $(brew --cellar)/*/*
else
echo "du -sch $(brew --cellar)/{${forms}}/*" | $SHELL
# bash -c "du -sch $(brew --cellar)/{${forms}}/*"
fi
}
echo zlib util-linux | du_wildcard
# NOTE: this was run after the above timed pipeline, which showed 'real 0m2.465s'
$ time { du -sch $(brew --cellar)/*/* | sort -k1h | tail; }
123M /home/linuxbrew/.linuxbrew/Cellar/ruby/3.3.1
172M /home/linuxbrew/.linuxbrew/Cellar/ghostscript/10.03.0
263M /home/linuxbrew/.linuxbrew/Cellar/boost/1.85.0
295M /home/linuxbrew/.linuxbrew/Cellar/go/1.22.3
363M /home/linuxbrew/.linuxbrew/Cellar/gcc/14.1.0
502M /home/linuxbrew/.linuxbrew/Cellar/binutils/2.42
1.1G /home/linuxbrew/.linuxbrew/Cellar/mingw-w64/11.0.1_1
1.1G /home/linuxbrew/.linuxbrew/Cellar/mingw-w64@11.0.1/11.0.1
2.8G /home/linuxbrew/.linuxbrew/Cellar/llvm/18.1.5
8.1G total
real 0m0.359s
user 0m0.067s
sys 0m0.308s
Thanks @redspot I've added an alternative using du -sch
This is identical to what @bkeys818 posted except it's compatible with the
fish
shell