[pacman-dev] [PATCHv2 1/2] contrib: adding pacsize
Pierre Neidhardt
ambrevar at gmail.com
Wed Mar 5 15:55:45 EST 2014
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 solution are wasting a lot of time -- only expac is faster);
- not rely on third-party tools.
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 at gmail.com>
---
contrib/.gitignore | 1 +
contrib/Makefile.am | 3 +
contrib/README | 4 ++
contrib/pacsize.sh.in | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 176 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..9be800d
--- /dev/null
+++ b/contrib/pacsize.sh.in
@@ -0,0 +1,168 @@
+#!/bin/sh
+# pacsize -- display package sizes
+#
+# Copyright (C) 2014 Pierre Neidhardt <ambrevar at 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 (/[\.,][^ ]*/, "")
+ split($2, a, " ")
+ printf ("%4d%s %s\n", a[1], a[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 at 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 -uh" ;;
+ 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 'BEGIN {
+ split("B KiB MiB GiB TiB PiB EiB ZiB YiB", unit)
+}
+/^%NAME%/ {
+ getline
+ pkg=$0
+}
+/^%SIZE%/ {
+ getline
+ size = $0
+ i = 1
+ while (size > 2048) {
+ size /= 1024
+ i++
+ }
+ printf ("%4d%s %s\n", size, unit[i], 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
More information about the pacman-dev
mailing list