apk search

How to look up things with Alpine Linux package manager

A bit -quiet or a little -verbose, apk search outputs a list of packages:

$ cat /etc/apk/repositories
#/media/cdrom/apks
http://dl-cdn.alpinelinux.org/alpine/v3.17/main
http://dl-cdn.alpinelinux.org/alpine/v3.17/community
http://dl-cdn.alpinelinux.org/alpine/edge/main
http://dl-cdn.alpinelinux.org/alpine/edge/community
#http://dl-cdn.alpinelinux.org/alpine/edge/testing

$ apk search "hack" | tee /dev/tty | wc -l
s6-2.11.3.2-r2
font-hack-3.003-r4
rust-1.71.1-r0
py3-subtesthack-0.2.0-r1
rust-1.64.0-r2
py3-setuptools-65.6.0-r0
daemontools-encore-1.11-r1
nethack-3.6.7-r0
py3-setuptools-68.0.0-r2
nethack-doc-3.6.7-r0
zfs-2.1.12-r0
font-hack-nerd-3.0.2-r0
py3-subtesthack-pyc-0.2.0-r1
13

$ alias 1="grep rust | head -1"

$ apk    search hack    | 1  # rust-1.71.1-r0
$ apk -v search hack    | 1  # rust-1.71.1-r0 - Rust Programming Language toolchain
$ apk    search hack -q | 1  # rust

There are lines without hack pattern in them. Why is that so? That's because apk search acts as a fancy grep over all fileds inside any APKINDEX file it could find locally. Here, p: means "provide" and D: means "depend". Highlighted line below reveals why rust package occured:

$ cd /var/cache/apk; ls -al
total 4404
drwxr-xr-x    2 root     root           120 Aug  9 14:02 .
drwxr-xr-x    4 root     root            80 Aug  9 13:58 ..
-rw-r--r--    1 root     root       1931593 Aug  9 14:02 APKINDEX.00163840.tar.gz
-rw-r--r--    1 root     root        450822 Aug  9 14:02 APKINDEX.066df28d.tar.gz
-rw-r--r--    1 root     root        656681 Aug  9 14:02 APKINDEX.85fe5889.tar.gz
-rw-r--r--    1 root     root       1460358 Aug  9 14:02 APKINDEX.b53994b4.tar.gz

$ tar -tOf *8d.tar.gz APKINDEX | grep -A13 -B1 "P:rust$"
C:Q1rOk4rSUpgkNoVpOxw2ARm4r17hw=
P:rust
V:1.71.1-r0
A:x86_64
S:193547354
I:622071808
T:Rust Programming Language toolchain
U:https://www.rust-lang.org/
L:Apache-2.0 AND MIT
o:rust
m:Jakub Panek <me@panekj.dev>
t:1691158261
c:70ce61bc0ba394fc0d0680f5ca9e7046b509fea6
D:gcc\
  musl-dev\
  so:libLLVM-16.so\
  so:libc.musl-x86_64.so.1\
  so:libgcc_s.so.1\
  so:libscudo.so\
  so:libstdc++.so.6
p:rust-bootstrap=1.71.1-r0\
  rust-stdlib=1.71.1-r0\
  so:libchalk_derive-1d53ee804995e4d5.so=0\
  so:libcstr-fdb59b5b50a9bd8c.so=0\
  so:libderive_more-539f099960be45c2.so=0\
  so:libdisplaydoc-e1eca0e134a3e6d0.so=0\
  so:libicu_provider_macros-db448138b24cd12b.so=0\
  so:libproc_macro_hack-2bd8753fce48ac00.so=0\
  so:librustc_driver-c37f132b6bcd4969.so=0\
  so:librustc_fluent_macro-ed05c935b195e10a.so=0\
  so:librustc_macros-7a5803295784a1d4.so=0\
  so:libserde_derive-3cf132afc55e3abd.so=0\
  so:libstd-09049943ce26e8ad.so=0\
  so:libtest-845ed5882612fa58.so=0\
  so:libthiserror_impl-f50746f2c83eae43.so=0\
  so:libtracing_attributes-9a7955890e4dca11.so=0\
  so:libunic_langid_macros_impl-4cf8b1b36598ab3f.so=0\
  so:libyoke_derive-164b4353d24f8c22.so=0\
  so:libzerofrom_derive-2ed30916df0ab153.so=0\
  so:libzerovec_derive-62b78484466b6427.so=0\
  cmd:rustc=1.71.1-r0\
  cmd:rustdoc=1.71.1-r0

By deafult, search is way relaxed. It globs your query and scans the fields. Tight it with --exact:

$ alias N="wc -l"

## `--exact`, `-x`, `-e` are all the same
$ apk search           rust      | N          # 39
$ apk search         '*rust*'    | N          # 39
$ apk search --exact   rust      | N          # 1
$ apk search -x       'rust*'    | N          # 19
$ apk search -e      '*rust'     | N          # 7
$ apk search         '*rust*' -e | N          # 39

## Note that this one takes no look at any `p:` or `D:` fields
$ apk search -v | grep rust | head -7
rustfmt-1.71.1-r0 - Rust Code Formatter
rust-gdb-1.71.1-r0 - GDB pretty printers for Rust
rust-1.71.1-r0 - Rust Programming Language toolchain
p11-kit-trust-0.25.0-r0 - System trust module from p11-kit
rust-1.64.0-r2 - The Rust Programming Language
libtpms-0.9.6-r0 - library providing software emulation of a Trusted Platform Module (TPM 1.2 and TPM 2.0)
monkeysphere-0.44-r1 - openpgp web of trust certification tools for SSH and TLS servers

## Grepping over name and description still does a good job
$ apk search -v | grep "text editor" | head -5
nano-doc-7.2-r1 - Enhanced clone of the Pico text editor (documentation)
gedit-doc-44.2-r3 - gedit is the GNOME text editor (documentation)
pluma-1.26.0-r5 - A small and lightweight UTF-8 text editor for the MATE
ed-1.19-r1 - Line-oriented text editor used to create, display, modify and otherwise manipulate text files
tau-0.12.0-r0 - GTK frontend for the Xi text editor, written in Rust

So the rule. Search becomes simpler with -eq. Here is some examples:

$ apk search rust -eq                      # Just toolchain
$ apk search '*-doc' -eq                   # List all available docs
$ apk search 'ip*-doc' '*wm*-doc' -ev      # Many at once
$ apk search '*-dev' -eq | grep curses     # Is there curses?
$ apk search '*-libs' -ev | grep http      # Any networking libraries?

## Another useful suffixes:
# - *-openrc
# - *-lang
# - *-completion
# - *-pyc
# - *-static

Next. What if you do not know the name of a package but know the name of a tool you need? Tighten thing using cmd:.

$ apk search cmd:vim        | N   # 5; what packages own executable
$ apk search 'cmd:vim*'     | N   # 5; same as above
$ apk search 'cmd:*vim*'    | N   # 7; not staring but containing `vim` in
$ apk search 'cmd:*vim*' -q | N   # 7; same as above
$ apk search -eq cmd:vim          # package with `vim` command inside - guaranteed!
gvim

Ok, but what actually matched with not exact query?

## Exact match; realxed would find also `cmd:ipython` or `cmd:iperf`
$ apk search -eq cmd:ip
iproute2-minimal

## `apk info pkg1 pkg2 .. pkgN` prints details of every `pkgX`; see `apk info -h`
$ apk info -v iproute2-minimal
iproute2-minimal: IP Routing Utilities (/sbin/ip only)
iproute2-minimal: https://wiki.linuxfoundation.org/networking/iproute2
iproute2-minimal: 644 KiB

## Let's combine; note that it's not exact match over `ip`
$ apk search cmd:ip -q | xargs apk info -P | grep -e ^cmd:ip -e provides: -e ^$ | head
iptstate-2.2.7-r0 provides:
cmd:iptstate=2.2.7-r0

iptables-1.8.8-r2 provides:
cmd:iptables-apply=1.8.8-r2
cmd:iptables-legacy-restore=1.8.8-r2
cmd:iptables-legacy-save=1.8.8-r2

## `-P` here stands for "provide": commands, libraries, pkg-config files and so on
$ apk info -P ripgrep libevent libevent-dev
ripgrep-13.0.0-r6 provides:
cmd:rg=13.0.0-r6

libevent-2.1.12-r7 provides:
so:libevent-2.1.so.7=7.0.1
so:libevent_core-2.1.so.7=7.0.1
so:libevent_extra-2.1.so.7=7.0.1
so:libevent_openssl-2.1.so.7=7.0.1
so:libevent_pthreads-2.1.so.7=7.0.1

libevent-dev-2.1.12-r7 provides:
pc:libevent=2.1.12-r7
pc:libevent_core=2.1.12-r7
pc:libevent_extra=2.1.12-r7
pc:libevent_openssl=2.1.12-r7
pc:libevent_pthreads=2.1.12-r7
cmd:event_rpcgen.py=2.1.12-r7

## `-R` stands for "require", i.e. dependencies
$ apk info -R iproute2 libevent libevent-dev
iproute2-6.0.0-r1 depends on:
iproute2-minimal
iproute2-tc
iproute2-ss
/bin/sh
so:libc.musl-x86_64.so.1
so:libcap.so.2
so:libmnl.so.0

libevent-2.1.12-r5 depends on:
so:libc.musl-x86_64.so.1
so:libcrypto.so.3
so:libssl.so.3

libevent-dev-2.1.12-r5 depends on:
python3
libevent=2.1.12-r5
pkgconfig

Need to know what packages use concrete binary or library?

## Print packages that use `wg-quick`; tiny `-r` means reverse search
$ apk search -eqr cmd:wg-quick
wireguard-tools
ifupdown-ng-wireguard-quick

## Again: this is what provides `libssl`...
$ apk search so:libssl
nss-3.92-r0
libssl3-3.0.10-r0
dovecot-2.3.20-r7
libssl1.1-1.1.1u-r1

## ...that is what use `libssl`...
$ apk search so:libssl | N
779

## ...provide pkg-config...
$ apk search 'pc:*curses'
ncurses-dev-6.4_p20230722-r0
notcurses-dev-3.0.9-r2

## ...and use Linux's netlink...
$ apk search -r so:libmnl | N
53

## ...number of packages depending on `musl`...
$ apk search -r musl | N
14145

## ...and total # of packages from available locally APKINDEXes.
$ apk search | N
23803

Key takeaways

## Bonus

$ apk info                     # installed packages
$ apk info zsh bash fish       # default to -dws (description, webpage, size)
$ apk info -a zsh bash fish    # all fields, but... for installed packages
$ apk info -v 'libre*'         # -dws in greppable format; `-v` verbose, remember?
$ apk info -W `which lbu`      # who owns this path, package must be installed
$ apk info -L musl-dev         # list of files installed by the package
$ apk info -r musl             # what depend on it in the system's `/etc/apk/world`

$ apk list -I                  # same as `apk info`
$ apk stats                    # just run it ;)
$ apk version -I               # all `APKINDEX`es yo have
$ apk version                  # things you have no up-to-date...
$ apk upgrade                  # ...so upgrade it
$ apk audit                    # see diversions from packages defaults