Printing package size is useful for maintenance. Indeed, the first entry on the wiki is focused on this topic: https://wiki.archlinux.org/index.php/Pacman_Tips#Maintenance None of the proposed solutions will allow you to: - select packages; - work on the output of other commands yielding a list of packages; - change the sorting; - be locale independent; - print a grand total; - be fast (most solutions are wasting a lot of time -- only expac is faster); - not rely on any third-party tool. Pacsize is a POSIX shell script that is generic enough to enclose all these features (and more). Adding a 'pacsize' script eliminates the unneeded abundance of workarounds for this simple matter. Signed-off-by: Pierre Neidhardt <ambrevar@gmail.com> --- contrib/.gitignore | 1 + contrib/Makefile.am | 3 + contrib/README | 4 ++ contrib/pacsize.sh.in | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 167 insertions(+) create mode 100644 contrib/pacsize.sh.in diff --git a/contrib/.gitignore b/contrib/.gitignore index a181813..9cecd5e 100644 --- a/contrib/.gitignore +++ b/contrib/.gitignore @@ -7,6 +7,7 @@ paclist paclog-pkglist pacscripts pacsearch +pacsize pacsysclean rankmirrors updpkgsums diff --git a/contrib/Makefile.am b/contrib/Makefile.am index f6ca3f1..8c5c6da 100644 --- a/contrib/Makefile.am +++ b/contrib/Makefile.am @@ -12,6 +12,7 @@ BASHSCRIPTS = \ paclist \ paclog-pkglist \ pacscripts \ + pacsize \ pacsysclean \ rankmirrors \ updpkgsums @@ -38,6 +39,7 @@ EXTRA_DIST = \ paclist.sh.in \ pacscripts.sh.in \ pacsearch.in \ + pacsize.sh.in \ pacsysclean.sh.in \ rankmirrors.sh.in \ updpkgsums.sh.in \ @@ -102,6 +104,7 @@ paclist: $(srcdir)/paclist.sh.in paclog-pkglist: $(srcdir)/paclog-pkglist.sh.in pacscripts: $(srcdir)/pacscripts.sh.in pacsearch: $(srcdir)/pacsearch.in +pacsize: $(srcdir)/pacsize.sh.in pacsysclean: $(srcdir)/pacsysclean.sh.in rankmirrors: $(srcdir)/rankmirrors.sh.in updpkgsums: $(srcdir)/updpkgsums.sh.in diff --git a/contrib/README b/contrib/README index ae33bb2..4f5c17f 100644 --- a/contrib/README +++ b/contrib/README @@ -31,6 +31,10 @@ pacsearch - a colorized search combining both -Ss and -Qs output. Installed packages are easily identified with a *** and local-only packages are also listed. +pacsize - display the size of packages. Duplicates are removed if any. The local +database is queried first; if the package is not found, the sync database is +then used for lookup. + pacsysclean - lists installed packages sorted by size. rankmirrors - ranks pacman mirrors by their connection and opening speed. diff --git a/contrib/pacsize.sh.in b/contrib/pacsize.sh.in new file mode 100644 index 0000000..4d84734 --- /dev/null +++ b/contrib/pacsize.sh.in @@ -0,0 +1,159 @@ +#!/bin/sh +# pacsize -- display package sizes +# +# Copyright (C) 2014 Pierre Neidhardt <ambrevar@gmail.com> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +readonly myname='pacsize' +readonly myver='@PACKAGE_VERSION@' + +calc_total () { + awk '{ + total += $1 + print +} +END { + printf ("%7s KIB TOTAL\n", total) +}' +} + +error () { + echo "$@" >&2 +} + +## Print size and name. We strip the arguably useless decimals. This makes +## output lighter. +filter () { + awk -F ": " \ + '$0 ~ "Name" { + pkg = $2 +} +$0 ~ "Installed Size" { + gsub (/[\.,].*/, "") + printf ("%7s KiB %s\n", $2, pkg) +}' +} + +remove_duplicates () { + awk '! table[$0]++' +} + +usage () { + cat <<EOF +Usage: ${1##*/} [OPTIONS] PACKAGES + ${1##*/} -a [OPTIONS] + +Display the size of PACKAGES. Duplicates are removed if any. The local database +is queried first; if the package is not found, the sync database is then used +for lookup. + +Options: + + -a: Process all installed packages. + -h: Show this help. + -n: Sort output by name. + -s: Sort output by size. + -t: Print total. + +Examples: + + $ ${1##*/} -ast + Convenient way to keep track of big packages. + + $ ${1##*/} \$(pactree -ld1 linux) + Print the size of linux and all its direct dependencies. + + $ ${1##*/} -st \$(pacman -Qdtq) + Print a grand total of orphan packages, and sort by size. +EOF +} + +version () { + echo "$myname $myver" + echo 'Copyright (C) 2014 Pierre Neidhardt <ambrevar@gmail.com>' +} + +opt_sort=false +opt_all=false +opt_total=false + +while getopts ":ahnstv" opt; do + case $opt in + a) + opt_all=true ;; + h) + usage "$0" + exit ;; + n) + opt_sort="sort -uk3" ;; + s) + opt_sort="sort -un" ;; + t) + opt_total="calc_total" ;; + v) + version "$0" + exit ;; + ?) + usage "$0" + exit 1 ;; + esac +done + +shift $(($OPTIND - 1)) + +## All-packages mode. +## We use a dedicated algorithm which is much faster than per-package mode. +## Unfortunately there is no easy way to select packages with this method. +if $opt_all; then + DBPath="$(awk -F = '/^ *DBPath/{print $2}' @sysconfdir@/pacman.conf 2>/dev/null)" + [ ! -d "$DBPath" ] && DBPath="@localstatedir@/lib/pacman" + + if [ ! -d "$DBPath/local/" ]; then + error "Could not find local database in $DBPath/local/." + exit 1 + fi + + awk '/^%NAME%/ { + getline + pkg=$0 +} +/^%SIZE%/ { + getline + size = $0 / 1024 + printf ("%6s KiB %s\n", size, pkg) +}' "$DBPath"/local/*/desc | ($opt_sort || cat) | ($opt_total || cat) + exit +fi + +## Per-package mode. +if [ $# -eq 0 ]; then + error "Missing argument." + usage "$0" + exit 1 +fi + +if ! command -v pacman >/dev/null 2>&1; then + error "'pacman' not found." + exit 1 +fi + +{ + ## If package is not found locally (-Q), we use the sync database (-S). We + ## use LC_ALL=C to make sure pacman output is not localized. + buffer=$(LC_ALL=C pacman -Qi "$@" 2>&1 1>&3 3>&- | cut -f2 -d "'") + [ -n "$buffer" ] && LC_ALL=C pacman -Si $buffer +} 3>&1 | filter | ($opt_sort || remove_duplicates) | ($opt_total || cat) + +# vim: set noet: -- 1.9.0