15

I am trying to get a list of installed packages with version in an easily processable format for an automated tool to parse.

I can get this output:

/ # apk list -i
WARNING: Ignoring APKINDEX.00740ba1.tar.gz: No such file or directory
WARNING: Ignoring APKINDEX.d8b2a6f4.tar.gz: No such file or directory
musl-1.1.22-r2 x86_64 {musl} (MIT) [installed]
zlib-1.2.11-r1 x86_64 {zlib} (zlib) [installed]
apk-tools-2.10.4-r2 x86_64 {apk-tools} (GPL2) [installed]
musl-utils-1.1.22-r2 x86_64 {musl} (MIT BSD GPL2+) [installed]
libssl1.1-1.1.1c-r0 x86_64 {openssl} (OpenSSL) [installed]
alpine-baselayout-3.1.2-r0 x86_64 {alpine-baselayout} (GPL-2.0-only) [installed]
alpine-keys-2.1-r2 x86_64 {alpine-keys} (MIT) [installed]
busybox-1.30.1-r2 x86_64 {busybox} (GPL-2.0) [installed]
scanelf-1.2.3-r0 x86_64 {pax-utils} (GPL-2.0) [installed]
libc-utils-0.7.1-r0 x86_64 {libc-dev} (BSD) [installed]
libtls-standalone-2.9.1-r0 x86_64 {libtls-standalone} (ISC) [installed]
ssl_client-1.30.1-r2 x86_64 {busybox} (GPL-2.0) [installed]
ca-certificates-cacert-20190108-r0 x86_64 {ca-certificates} (MPL-2.0 GPL-2.0-or-later) [installed] 
libcrypto1.1-1.1.1c-r0 x86_64 {openssl} (OpenSSL) [installed]

However, packages names can contain hyphens and versions are seperated by hyphens, this makes it impossible to reliably parse this result.

Is there any way to get this info in an easier to parse format? JSON would be amazing but a simple tab separated table would be fine.

Thanks!

3 Answers3

5

However, packages names can contain hyphens and versions are seperated by hyphens, this makes it impossible to reliably parse this result.

Versions themselves cannot contain hyphens – there is always exactly one group for the pkgver field and always exactly one for the pkgrel. So it's actually very easy to parse by separating the last two dash-separated groups; the package name is what remains.

Most programming languages can do so using either a regex, or functions like .rsplit() / .rindex().

For example, this PCRE regex will match all fields:

/(.+)-([^-]+)-r([^-]+) (\S+) \{(\S+)\} \((.+?)\)/

To generate something like JSON output with that, use:

apk list -i | perl -MJSON -E 'print encode_json([map {
                                @foo{qw(pkgname pkgver pkgrel arch group license)} =
                                /(.+)-([^-]+)-r([^-]+) (\S+) \{(\S+)\} \((.+?)\)/;
                                \%foo
                              } <>])'
grawity
  • 501,077
1

This approach preserves revisions without requiring them, depends on sed only, invokes sed just once and doesn't use the non-standard \d for digits.

apk list -I | sed 's/ .*//;s/-\(r[0-9]\+\)$/@@\1/;s/\(.*\)-/\1 /;s/@@/-/'

Explanation:

  • remove the first space and all text after it
  • if -rNUM is at the end, turn it into @@rNUM
  • turn the last dash into space (i.e. the version separator)
  • turn @@ back to -

Example output:

uhttpd-mod-ubus 2023.06.25~34a8a74d-r4
urandom-seed 3
urngd 2023.11.01~44365eb1-r1
usign 2020.05.23~f1f65026-r1
wifi-scripts 1.0-r1
wireless-regdb 2024.10.07-r1
proski
  • 171
0

Here is another one-liner, without perl:

apk list -I | cut -f1 -d' ' | sed -e 's/-r\d\+$//'| sed -e 's/\(.*\)-/\1 /'

Explanation:

Example output:

% apk list -I | cut -f1 -d' ' | sed -e 's/-r\d\+$//'| sed 's/\(.*\)-/\1 /' | head
abuild 3.13.0
abuild-sudo 3.13.0
ack 3.7.0
agetty 2.40.1
agetty-openrc 0.54.2
alpine-base 3.21.0_alpha20240606
alpine-baselayout 3.6.5
alpine-baselayout-data 3.6.5
alpine-conf 3.18.1
alpine-keys 2.4

...which you can easily part, given the space split.

thiagowfx
  • 1,808