You are not logged in.

#1 2007-08-22 13:11:12

byte
Member
From: Düsseldorf (DE)
Registered: 2006-05-01
Posts: 2,046

Sort installed pkgs by size

Copy and paste it, put it in a shell script, whatever:

(echo PACKAGE SIZE; \
  for A in $(pacman -Q | cut -d' ' -f1); do
    echo -n $A; LANG= pacman -Qi $A | grep ^Installed \
    | sed 's/.*: *\([0-9]*\)\..*/ \1/'; \
  done \
  | sort -nrk2) \
| column -t

I'll try to post a different version later which won't use pacman directly, because it's rather slow.

Last edited by byte (2007-08-22 13:13:27)


1000

Offline

#2 2007-08-22 13:22:22

shining
Pacman Developer
Registered: 2006-05-10
Posts: 2,043

Re: Sort installed pkgs by size

Maybe you could work something out from "pacman -Qi" if it worked.
Currently the i option is ignored when no targets are specified, but it works in pacman git (so it should be in 3.1) smile

LANG=C pacman -Qi |grep -E "Name|Size" | head -n 20
Name           : a52dec
Installed Size : 123.27 K
Name           : abcde
Installed Size : 141.26 K
Name           : acl
Installed Size : 257.51 K
Name           : acpi
Installed Size :  22.55 K
Name           : aiksaurus
Installed Size : 707.32 K
Name           : alsa-lib
Installed Size : 1541.02 K
Name           : alsa-utils
Installed Size : 1572.33 K
Name           : amrnb
Installed Size : 634.03 K
Name           : apache-ant
Installed Size : 3267.89 K
Name           : apr
Installed Size : 1066.46 K

pacman roulette : pacman -S $(pacman -Slq | LANG=C sort -R | head -n $((RANDOM % 10)))

Offline

#3 2007-08-22 14:21:08

byte
Member
From: Düsseldorf (DE)
Registered: 2006-05-01
Posts: 2,046

Re: Sort installed pkgs by size

(echo PACKAGE SIZE; \
  for A in /var/lib/pacman/local/*/desc; do
    (sed -n 2p $A; grep -E '^[0-9]{2,}$' $A) | tr '\n' ' '; echo
  done \
  | sort -nrk2) \
| column -t

That's better. Shorter and at least 5 times faster for me. :]


1000

Offline

#4 2007-08-22 14:43:52

byte
Member
From: Düsseldorf (DE)
Registered: 2006-05-01
Posts: 2,046

Re: Sort installed pkgs by size

http://bbs.archlinux.org/viewtopic.php?t=20971 is related, also see pactools (pt-pacsize).


1000

Offline

#5 2007-08-22 22:43:54

shining
Pacman Developer
Registered: 2006-05-10
Posts: 2,043

Re: Sort installed pkgs by size

I timed the two scripts, I get very weird result :

with pacman 3.1 :

sh test1.sh > /dev/null  8,84s user 4,44s system 154% cpu 8,593 total
LANG=C sh test1.sh > /dev/null  5,98s user 6,30s system 104% cpu 11,743 total

with pacman 3.0 :

sh test1.sh > /dev/null  11,69s user 5,03s system 145% cpu 11,506 total
LANG=C sh test1.sh > /dev/null  9,42s user 6,21s system 103% cpu 15,066 total

using database directly :

sh test2.sh > /dev/null  10,20s user 1,75s system 97% cpu 12,213 total
LANG=C sh test2.sh > /dev/null  0,65s user 1,97s system 111% cpu 2,351 total

Any ideas why the first script test1.sh is slower using LANC=C ?


pacman roulette : pacman -S $(pacman -Slq | LANG=C sort -R | head -n $((RANDOM % 10)))

Offline

#6 2007-08-22 22:51:27

shining
Pacman Developer
Registered: 2006-05-10
Posts: 2,043

Re: Sort installed pkgs by size

Here is a very ugly script using the new -Qi behavior in 3.1 :

#!/bin/sh
(n=0
for i in $(LANG=C pacman -Qi |grep -E "Name|Size"  | cut -d':' -f2); do
  if [ $n -eq "0" ]; then
    name=$i
  elif [ $n -eq "1" ]; then
    size=${i%.*}
  elif [ $n -eq "2" ]; then
    echo $name $size
  fi
  n=$(((n+1)%3))
done
) | sort -nrk2 | column -t

I think it's a very very ugly way for converting :

Name           : a52dec
Installed Size : 123.27 K
Name           : abcde
Installed Size : 141.26 K

to

a52dec 123
abcde 141

But well, it's faster than the previous ones :

sh test3.sh  0,40s user 0,06s system 115% cpu 0,391 total

pacman roulette : pacman -S $(pacman -Slq | LANG=C sort -R | head -n $((RANDOM % 10)))

Offline

#7 2007-08-22 23:44:38

shining
Pacman Developer
Registered: 2006-05-10
Posts: 2,043

Re: Sort installed pkgs by size

I wrote this using libalpm for fun.
Note that due to a stupid mistake in pacman 3.0 where most of the list function weren't exported, I had to copy/paste them.
So first half of the file shouldn't be needed. And the actual code doing the job is just 5 lines..

/*
 *  displaypkg.c : Display the locally installed packages sorted by size.
 *
 */

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>

#include <alpm.h>
#include <alpm_list.h>

alpm_list_t *list_nth(alpm_list_t *list, int n)
{
    alpm_list_t *i = list;
    while(n--) {
        i = i->next;
    }
    return(i);
}

alpm_list_t *list_mmerge(alpm_list_t *left, alpm_list_t *right, alpm_list_fn_cmp fn)
{
    alpm_list_t *newlist, *lp;

    if (left == NULL) 
        return right;
    if (right == NULL)
        return left;

    if (fn(left->data, right->data) <= 0) {
        newlist = left;
        left = left->next;
    }
    else {
        newlist = right;
        right = right->next;
    }
    newlist->prev = NULL;
    newlist->next = NULL;
    lp = newlist;

    while ((left != NULL) && (right != NULL)) {
        if (fn(left->data, right->data) <= 0) {
            lp->next = left;
            left->prev = lp;
            left = left->next;
        } 
        else {
            lp->next = right;
            right->prev = lp;
            right = right->next;
        }
        lp = lp->next;
        lp->next = NULL;
    }
    if (left != NULL) {
        lp->next = left;
        left->prev = lp;
    }
    else if (right != NULL) {
        lp->next = right;
        right->prev = lp;
    }
    return(newlist);
}

alpm_list_t *list_msort(alpm_list_t *list, int n, alpm_list_fn_cmp fn)
{
    if (n > 1) {
        alpm_list_t *left = list;
        alpm_list_t *lastleft = list_nth(list, n/2 - 1);
        alpm_list_t *right = lastleft->next;
        /* terminate first list */
        lastleft->next = NULL;    

        left = list_msort(left, n/2, fn);
        right = list_msort(right, n - (n/2), fn);
        list = list_mmerge(left, right, fn);
    }
    return(list);
}

int _alpm_pkg_cmp(const void *v1, const void *v2)
{
  pmpkg_t *p1 = (pmpkg_t *)v1;
  pmpkg_t *p2 = (pmpkg_t *)v2;
  unsigned long int s1 = alpm_pkg_get_size(p1);
  unsigned long int s2 = alpm_pkg_get_size(p2);
  return(s2 - s1);
}

int main(int argc, char **argv)
{
  pmdb_t *db = NULL;
  alpm_list_t *i;

  if(alpm_initialize() == -1) {
    fprintf(stderr, "cannot initialize alpm: %s\n", alpm_strerror(pm_errno));
    exit(EXIT_FAILURE);
  }

  /* let us get log messages from libalpm */
  alpm_option_set_dbpath("/var/lib/pacman");

  db = alpm_db_register("local");
  if(db == NULL) {
    fprintf(stderr, "error: could not register 'local' database (%s)\n",
        alpm_strerror(pm_errno));
    exit(EXIT_FAILURE);
  }

  alpm_list_t *list = alpm_db_getpkgcache(db);
  list = list_msort(list, alpm_list_count(list), _alpm_pkg_cmp);

  for(i = list; i; i = alpm_list_next(i)) {
    pmpkg_t *pkg = alpm_list_getdata(i);
    printf("%s %lu\n", alpm_pkg_get_name(pkg), alpm_pkg_get_size(pkg)/1024);
  }

  if(alpm_release() == -1) {
    fprintf(stderr, "error releasing alpm: %s\n", alpm_strerror(pm_errno));
  }

  exit(EXIT_SUCCESS);
}
compile :
$ gcc displaypkg.c -o displaypkg -lalpm -Wall
run :
$ time (./displaypkg | column -t)
(; ./displaypkg | column -t; )  0,01s user 0,00s system 11% cpu 0,071 total

Last edited by shining (2007-08-23 21:11:36)


pacman roulette : pacman -S $(pacman -Slq | LANG=C sort -R | head -n $((RANDOM % 10)))

Offline

#8 2007-08-23 10:41:18

test1000
Member
Registered: 2005-04-03
Posts: 834

Re: Sort installed pkgs by size

hmm:

kris ~/bin $ gcc displaypkg.c -o displaypkg -lalpm -Wall
displaypkg.c:12: error: conflicting types for 'alpm_list_nth'
/usr/include/alpm_list.h:59: error: previous declaration of 'alpm_list_nth' was here


KISS = "It can scarcely be denied that the supreme goal of all theory is to make the irreducible basic elements as simple and as few as possible without having to surrender the adequate representation of a single datum of experience." - Albert Einstein

Offline

#9 2007-08-23 21:01:49

shining
Pacman Developer
Registered: 2006-05-10
Posts: 2,043

Re: Sort installed pkgs by size

Oh, I see, I copied the list functions from 3.1 instead of from 3.0 , and they changed slightly (added some const).
I didn't notice this problem because I've the 3.0 alpm.h in /usr/include/ and 3.1 alpm.h in /usr/local/include.
I didn't know /usr/local/include was used first. And I don't even know how to configure that.

I think you just need to remove the two const on lines 11 and 13, but I'll update it above.

Edit : hm, I should as well rename the list functions, so that there are no conflicts possible. And rename them back later for 3.1 .

Last edited by shining (2007-08-23 21:09:59)


pacman roulette : pacman -S $(pacman -Slq | LANG=C sort -R | head -n $((RANDOM % 10)))

Offline

#10 2007-12-09 07:45:04

byte
Member
From: Düsseldorf (DE)
Registered: 2006-05-01
Posts: 2,046

Re: Sort installed pkgs by size

#!/bin/bash
( echo "PACKAGE SIZE(K)";
for A in /var/lib/pacman/local/*/desc; do
  egrep -A1 '%(NAME|SIZE)' $A  \
   | gawk '/^[a-z]/ { printf "%s ", $1 }; /^[0-9]/ { printf "%.0f\n", $1/1024 }'
done | sort -nrk2 ) | column -t

The old one (post #3) ceased working after some packages appeared with a BUILDDATE field containing pure numeric values (unix epoch time, hi phrakture tongue).
This version is more robust, more complex, and MOAR FASTARR!! smile


1000

Offline

Board footer

Powered by FluxBB