“What did this package install?” sounds like one question, but administrators usually mean one of four things: list paths owned by an installed package, preview an uninstalled repository package, identify the owner of one existing path, or inspect a downloaded archive. Pick the matching database so the result is evidence rather than guesswork.

Package-owned is not the same as package-created

  • A manifest/database records paths shipped or registered as owned by the package.

  • Maintainer scripts can create users, directories, caches, databases, symlinks, generated configuration, and service state not represented like ordinary payload files.

  • Applications create logs, uploads, caches, user preferences, and runtime state after installation.

  • Configuration-management and administrators can change package-owned files.

  • Containers, alternatives systems, diversions, overlays, and immutable images can change what appears at a path.

Debian and Ubuntu: list installed package paths

Debian or Ubuntu shellbash
dpkg-query -W -f="${binary:Package} ${Version} ${Architecture} ${db:Status-Abbrev}\n" curl
dpkg-query -L curl
curl 8.x... amd64 ii 
/.
/usr
/usr/bin
/usr/bin/curl
/usr/share/doc/curl
...

Confirm the exact package before trusting the list

  • -W selects package records and the format prints name, version, architecture, and abbreviated status.

  • -L lists paths associated with the installed package.

  • A command can be split across a main package, common/data package, library package, and documentation package.

  • Multiarch installations may require package:architecture to disambiguate.

  • The output includes directories and may include conffile paths; it does not prove current content integrity.

Find which installed Debian package owns a path

Debian or Ubuntu shellbash
command -v curl
dpkg-query -S /usr/bin/curl
dpkg-query -S '*/libcurl.so.*'
/usr/bin/curl
curl: /usr/bin/curl
libcurl4:amd64: /usr/lib/x86_64-linux-gnu/libcurl.so.4.8.0
libcurl4:amd64: /usr/lib/x86_64-linux-gnu/libcurl.so.4

Search exact paths before using patterns

  • command -v resolves the executable selected by the current shell environment.

  • dpkg-query -S searches installed package ownership records.

  • Quote glob characters so the shell does not expand them first.

  • Several packages can report related paths, diversions, or overlapping metadata cases.

  • No result can mean an unpackaged/generated file, different root/container, symlink target issue, or database inconsistency.

List only Debian conffiles

Debian or Ubuntu shellbash
dpkg-query -W -f="${Conffiles}\n" openssh-server
 /etc/init.d/ssh <md5>
 /etc/pam.d/sshd <md5>
 /etc/ssh/sshd_config <md5>
...

Conffiles have upgrade/removal semantics

  • The field lists files tracked as Debian conffiles for that package.

  • Recorded hashes help dpkg decide whether the administrator modified a conffile.

  • Not every application configuration is necessarily a dpkg conffile.

  • Package removal and purge treat configuration state differently.

  • Do not replace/remove config based on the manifest alone; back up and understand local changes.

Preview an uninstalled Debian repository package

Debian or Ubuntu shellbash
sudo apt update
sudo apt install apt-file
apt-file list nginx-core
apt-file search --fixed-string /usr/sbin/nginx
nginx-core: /usr/sbin/nginx
...
nginx-core: /usr/sbin/nginx

Risk level: caution. Review the command before running it.

apt-file searches repository Contents indexes

  • apt-file list can inspect package paths without installing/fetching the package.

  • search answers which indexed repository packages contain a matching file.

  • Repository source/suite/architecture configuration controls results.

  • Contents indexes can be missing/stale for some repositories; update and inspect configured indices when results surprise you.

  • Installing apt-file changes the host; review APT’s proposed transaction.

Inspect a downloaded DEB without installing it

Directory containing a trusted .deb filebash
dpkg-deb --info ./package_version_arch.deb
dpkg-deb --contents ./package_version_arch.deb
 new Debian package, version 2.0.
 Package: example
 Version: ...
drwxr-xr-x root/root ... ./usr/
-rwxr-xr-x root/root ... ./usr/bin/example

Archive inspection is read-only metadata work

  • --info reads control metadata and --contents lists the data archive.

  • This does not install files or execute maintainer scripts.

  • A downloaded archive may differ from the repository candidate or installed version/architecture.

  • Verify origin/signature/hash through the package-manager/repository workflow before trusting content.

  • Do not extract unknown packages into sensitive directories or execute included programs.

RPM systems: list installed package files

Fedora, RHEL, Rocky, AlmaLinux, openSUSE, or another RPM systembash
rpm -q bash
rpm -ql bash
rpm -qc bash
rpm -qd bash
bash-5.x...
/etc/bashrc
/usr/bin/bash
...
... configuration files ...
... documentation files ...

RPM query selectors can narrow the manifest

  • -q queries the installed RPM database by package name.

  • -l lists package paths; -c limits to configuration files; -d limits to documentation.

  • Package labels/names vary by distribution and installed architecture.

  • rpm -qlv or query formats can include permissions, owner, size, digest-related metadata, and flags.

  • Database output is not a live ls; verify current filesystem state separately.

Find the installed RPM owner of a file

RPM-based Linux shellbash
rpm -qf /usr/bin/bash
rpm -q --queryformat '[%{=NAME} %{FILEMODES:perms} %{FILENAMES}\n]' bash | head
bash-5.x...
bash -rwxr-xr-x /usr/bin/bash
...

Query formats are useful for audits

  • -f selects the installed package owning an exact path.

  • The iterator walks parallel file metadata arrays in the RPM header.

  • =NAME locks the scalar package name while filenames iterate.

  • Query the real resolved path when symlinks obscure ownership.

  • Do not parse human-formatted verbose output when a documented query format can provide stable fields.

Preview repository RPM contents

DNF-based Linux shellbash
dnf repoquery --available --location bash
dnf repoquery --available --list bash
dnf provides '*/bin/bash'
... repository package location ...
/usr/bin/bash
...
bash-... : The GNU Bourne Again shell

Repository state determines the answer

  • repoquery --list lists payload paths for available repository packages without installing them.

  • dnf provides searches providers of a path/pattern.

  • Enabled repositories, modules, release version, architecture, exclusions, and metadata freshness matter.

  • Several versions/architectures/providers may match.

  • Refresh metadata through the organization’s normal repository policy before making install decisions.

Inspect a downloaded RPM

Directory containing a trusted RPM filebash
rpm -qpi ./package-version.arch.rpm
rpm -qlp ./package-version.arch.rpm
rpm -Kv ./package-version.arch.rpm
Name : example
Version : ...
...
/usr/bin/example
...
... digests signatures OK

The -p selector means package file

  • -qpi reads archive information and -qlp lists its file manifest.

  • -Kv checks the signatures/digests that the local RPM keyring understands.

  • “OK” is meaningful only if trusted correct signing keys and policy are configured.

  • Archive inspection does not execute scripts or install content.

  • Prefer repository/package-manager download and verification workflows over random RPM downloads.

Arch Linux commands

Arch Linux shellbash
pacman -Q bash
pacman -Ql bash
pacman -Qo /usr/bin/bash
sudo pacman -Fy
pacman -F /usr/bin/bash
bash ...
bash /usr/bin/bash
/usr/bin/bash is owned by bash ...
... sync file databases ...
core/bash ... usr/bin/bash

Local and sync file databases are distinct

  • -Ql lists installed package files; -Qo finds installed ownership.

  • -F searches synchronized repository file databases, including uninstalled packages.

  • -Fy refreshes file databases and requires privileges/network; use distribution guidance to avoid partial/unsafe update habits.

  • Package names/repos can differ across configured mirrors.

  • Generated/unowned paths remain outside the packaged file database.

Alpine Linux commands

Alpine Linux shellsh
apk info -e busybox
apk info -L busybox
apk info -W /bin/busybox
busybox
busybox-... contains:
/bin/busybox
...
/bin/busybox is owned by busybox-...

Ask the installed database first

  • -e tests whether the named package is installed.

  • -L lists installed package contents.

  • -W reports ownership of a path according to the installed database.

  • BusyBox applets may be symlinks to one binary; inspect link targets as well as owners.

  • Repository package/archive queries use different apk options and configured indexes; pin commands to the deployed Alpine release.

Verify whether installed payload files changed

Linux hostbash
# Debian/Ubuntu (installed package checksums when available)
debsums curl

# RPM systems
rpm -V bash
No output commonly means checked files match recorded metadata; differences produce package-tool-specific markers. Missing checksum coverage and configuration-file policy vary.

Verification needs careful interpretation

  • debsums may need installation and not every package/file has checksum coverage.

  • rpm -V compares recorded attributes and reports compact difference markers.

  • Legitimate administrator/configuration changes can appear.

  • A clean verification does not prove the whole system is uncompromised; package databases/tools can be attacked too.

  • Investigate differences using trusted repositories, logs, deployment state, incident procedures, and file ownership—not automatic overwrites.

Why files may not appear in the manifest

  • Post-install/pre/post transaction scripts generated them.

  • A service created databases, caches, keys, certificates, sockets, PID files, logs, or state.

  • A tmpfiles/sysusers mechanism creates paths at boot/install/runtime.

  • An alternatives/diversion mechanism owns a selected symlink/path.

  • An administrator, configuration manager, installer, language package manager, Flatpak/Snap/container, or application updater created them.

  • The path is a mount/overlay bind rather than a file from the host package payload.

Package database versus live filesystem

  • A manifest can list a path that has since been deleted or replaced.

  • Permissions, owners, symlink targets, hashes, and capabilities can drift.

  • A package upgrade may preserve locally modified configuration or create .dpkg-dist, .rpmnew, or similar artifacts.

  • Files may belong to a package in another container/chroot/root filesystem than the shell you queried.

  • Architecture/multilib versions can install related paths under separate prefixes.

  • Use status/verification tools and live stat/readlink/getcap evidence for the actual filesystem.

Safe automation patterns

package-files.shbash
#!/usr/bin/env bash
set -euo pipefail
 
package=${1:?usage: package-files.sh PACKAGE}
 
if command -v dpkg-query >/dev/null 2>&1; then
  dpkg-query -W -f='${db:Status-Abbrev}\n' -- "$package" | grep -qx 'ii '
  dpkg-query -L -- "$package"
elif command -v rpm >/dev/null 2>&1; then
  rpm -q -- "$package" >/dev/null
  rpm -ql -- "$package"
else
  printf 'Unsupported package manager\n' >&2
  exit 2
fi

Fail closed on unsupported or absent packages

  • set -euo pipefail makes unexpected failures visible.

  • A required positional argument prevents an accidental query of everything.

  • The Debian branch verifies fully installed abbreviated state before listing.

  • -- ends option parsing for user-supplied package names where supported.

  • Production inventory should emit a defined machine-readable format, package version/architecture/root, exit codes, and tool versions.

Troubleshooting no-result cases

  • Package not installed: use repository query/index or inspect the downloaded archive.

  • Command name differs from package name: query the executable path owner first.

  • Path is a symlink: inspect both link and resolved target ownership.

  • apt-file finds nothing: update/check Contents indexes, repositories, suite, origin, and architecture.

  • DNF returns many providers: constrain release, architecture, repo, module, version, and exact path.

  • File is unowned: check scripts/runtime/config management/other package systems/containers before cleanup.

  • Wrong filesystem root: enter/query the container, chroot, sysroot, or use supported alternate-root options.

  • Database says owned but file missing: verify package status/integrity, logs, overlay, local deletion, and reinstall policy.

Forensic and compliance caveats

  • Package manifests are one provenance source, not a complete software bill of materials.

  • Maintainer scripts, downloaded plugins/models, vendored dependencies, containers, and application self-updates need separate inventory.

  • Do not execute suspect binaries or package scripts while investigating.

  • Capture hashes, metadata, package database, logs, mounts, and repository/key configuration according to incident procedures.

  • Query output can reveal sensitive paths/software; sanitize before sharing.

  • For strong evidence, collect from a trusted environment and preserve chain of custody.

Command decision table

  • Installed Debian package → dpkg-query -L; owner → dpkg-query -S.

  • Uninstalled Debian repository package → apt-file list; provider → apt-file search.

  • Downloaded DEB → dpkg-deb --contents.

  • Installed RPM package → rpm -ql; owner → rpm -qf.

  • Uninstalled RPM repository package → dnf repoquery --list; provider → dnf provides.

  • Downloaded RPM → rpm -qlp plus signature/digest verification.

  • Arch installed/repository → pacman -Ql/-Qo or pacman -F.

  • Alpine installed → apk info -L/-W.

Verification checklist

  • Distribution, release, architecture, root/container, repository set, package name, version, and install status are known.

  • The query source matches the question: installed DB, repository index, or archive.

  • Ownership and symlink/resolved-target behavior are checked for individual paths.

  • Config/docs and integrity attributes are queried when relevant.

  • Generated/runtime/local/other-package-system files are not mistaken for manifest payload.

  • Results and exit codes are captured reproducibly without destructive cleanup or untrusted execution.

Primary references

  • dpkg-query manual documents installed package listing, search, status, formats, and exit behavior.

  • Ubuntu apt-file manual documents repository Contents list/search, index limitations, filters, and exit codes.

  • dpkg-deb manual documents DEB archive information/content inspection.

  • RPM manual documents installed/archive selectors, file lists, config/docs, ownership, verification, and signatures.

  • RPM query-format manual documents file metadata iteration for automation.

  • Use the installed distribution’s man pages for exact DNF, pacman, and apk behavior because releases/options evolve.