How to List Installed Packages on Ubuntu 26.04, 24.04 and 22.04

Last updated Thursday, May 7, 2026 2:22 pm Joshua James 6 min read

Listing installed packages on Ubuntu becomes important as soon as a workstation, server, or VM has lived through several updates. A clean package inventory helps you spot what changed, rebuild another machine, and avoid guessing before cleanup or migration work.

The same APT and dpkg package-listing commands work on Ubuntu 26.04 LTS, 24.04 LTS, and 22.04 LTS, but output headers and APT warning text can differ. Use apt list --installed for fast interactive checks, dpkg --list for package state, dpkg-query for repeatable reports, and apt-mark when cleanup depends on manual versus automatic install flags. Snap and Flatpak apps live outside the dpkg database, so check those managers separately when they are present.

Choose the right command to list installed packages on Ubuntu

If you are troubleshooting dependency issues, checking free space, preparing a migration baseline, or planning a rebuild, an installed package list is your source of truth. A single flat list can hide useful clues, so choose the command based on the question you need to answer.

GoalBest commandWhy
Quickly see installed package names and versionsapt list --installedReadable for human review, but not the best source for scripts
Read package status codes and verify broken statesLC_ALL=C dpkg --listShows state flags such as ii and rc with an ASCII header
Inspect one installed package or file ownerdpkg-query --status, dpkg-query --searchConfirms the local package record and which package owns a file
Build scripts and custom reportsdpkg-query --show --showformat='...'Predictable fields without APT progress or warning text
Distinguish manually installed packages from dependenciesapt-mark showmanual, apt-mark showautoUseful before pruning packages or rebuilding another system
Check packages managed outside APTsnap list, flatpak list --appShows store-managed apps that APT and dpkg do not report
Review recent package install historygrep or zgrep on /var/log/dpkg.log*Shows recent package changes when log retention still covers them

Use apt list for a fast Ubuntu package inventory

Start with apt list --installed when you need an on-screen inventory that includes package name, source pocket, version, architecture, and install marker.

apt list --installed

The output is meant for people, not automation. It may print APT’s unstable-CLI warning on stderr, so use dpkg-query later when a script needs stable fields. After any warning text, example package rows look like this:

Listing...
accountsservice/resolute,now 23.13.9-8ubuntu5 amd64 [installed,automatic]
acl/resolute,now 2.3.2-2 amd64 [installed,automatic]
adduser/resolute,now 3.153ubuntu1 all [installed,automatic]

To limit output for quick review, combine apt list with the grep command in Linux. Redirecting stderr keeps APT’s scripting warning out of the filtered result:

apt list --installed 2>/dev/null | grep -i "^linux-image" | head -n 20

That filter focuses on installed kernel image packages. Change the quoted prefix to another package family, such as python3- or libssl, when you need a different slice.

Use dpkg to read Ubuntu package state flags

dpkg --list is better when package state matters. The first columns show the desired action, current status, and error state, so you can distinguish installed packages from removed packages that still leave configuration files behind.

LC_ALL=C dpkg --list | head -n 20

LC_ALL=C keeps the header in an ASCII format, which is useful on Ubuntu 26.04 and newer systems where localized output can use box-drawing characters. Typical states include ii for fully installed packages and rc for removed packages that still keep conffiles.

+-- Desired=Unknown/Install/Remove/Purge/Hold
|+- Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
||+ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||| Name                                       Version                                    Architecture Description
+++-==========================================-==========================================-============-================================================================================
ii  accountsservice                            23.13.9-8ubuntu5                           amd64        query and manipulate user account information
ii  acl                                        2.3.2-2                                    amd64        access control list - utilities
ii  adduser                                    3.153ubuntu1                               all          add and remove users and groups

For a compact list of only fully installed packages, switch to dpkg-query and filter for the ii state:

LC_ALL=C dpkg-query --show --showformat='${db:Status-Abbrev}\t${binary:Package}\t${Version}\n' | grep '^ii' | head -n 40

dpkg-query skips the header row and keeps the output compact for scripts, audits, and diff checks.

To check one package without scanning the full inventory, pass the package name to dpkg-query. An installed package returns a line beginning with ii; no output usually means the package is absent or no longer fully installed.

LC_ALL=C dpkg-query --show --showformat='${db:Status-Abbrev} ${binary:Package} ${Version}\n' bash 2>/dev/null | grep '^ii'

The version field changes by Ubuntu release, but the installed-state prefix should stay visible:

ii  bash 5.3-2ubuntu1

Inspect one installed package and its files

After you find a package in the inventory, inspect the local dpkg record before you troubleshoot dependencies, file paths, or configuration ownership. A narrow status filter keeps the important local metadata easy to scan:

dpkg-query --status bash | grep -E '^(Package|Status|Architecture|Version):'

Relevant fields look like this for an installed package:

Package: bash
Status: install ok installed
Architecture: amd64
Version: 5.3-2ubuntu1

List package files when you need to locate documentation or default configuration files:

dpkg-query --listfiles bash | grep -E '^/(etc/bash.bashrc|usr/share/doc/bash/copyright)$'
/etc/bash.bashrc
/usr/share/doc/bash/copyright

Reverse the lookup with dpkg-query --search when you have a file path and need to know which package owns it:

dpkg-query --search /etc/bash.bashrc
bash: /etc/bash.bashrc

Use apt-mark to split manual and automatic Ubuntu packages

Before removing unused software, check which packages are marked manual. Manual packages usually represent choices made by an administrator, while automatic packages were pulled in as dependencies.

Show manually installed packages with apt-mark

apt-mark showmanual

Use this output before a migration to identify core packages and tools that were intentionally installed.

ca-certificates
dash
diffutils
findutils
grep
gzip

For rebuild planning, save the manual list instead of exporting every dependency from dpkg. APT can pull dependencies back in when you install the selected manual packages on a new system.

apt-mark showmanual | sort > "$HOME/ubuntu-manual-packages.txt"

The redirect writes the list to ubuntu-manual-packages.txt and does not print package names on screen when it succeeds.

Use this file as a rebuild checklist. Review it before feeding it to another system because package names, transitional packages, and desktop defaults can change between Ubuntu releases.

Show automatically installed dependency packages with apt-mark

apt-mark showauto

Everything in this list should be reviewed as dependency state, not a purge queue. A package can be automatic and still required by another installed package.

accountsservice
acl
adduser
adwaita-icon-theme
alsa-base
alsa-topology-conf

List Snap and Flatpak packages outside APT

APT, dpkg, and apt-mark focus on DEB packages managed through Ubuntu’s package database. Ubuntu Desktop commonly has Snap packages, and customized systems may also have Flatpak apps, so list those package managers separately before calling an inventory complete.

Use snap list only when the Snap command exists on the system:

if command -v snap >/dev/null 2>&1; then
    snap list
else
    echo "snap is not installed"
fi

Flatpak is not installed on Ubuntu by default. If you use Flathub applications and the command is missing, set up Flatpak first with the Flatpak installation guide for Ubuntu.

Use flatpak list --app for Flatpak applications:

if command -v flatpak >/dev/null 2>&1; then
    flatpak list --app --columns=application,name,version,branch,origin
else
    echo "flatpak is not installed"
fi

Create repeatable Ubuntu package reports with dpkg-query

When you need data ready for scripts, ticket attachments, or before-and-after comparisons, use field-level output and save it to a file you control.

LC_ALL=C dpkg-query --show --showformat='${db:Status-Abbrev}\t${binary:Package}\t${Version}\t${Architecture}\n' | grep '^ii' | sort > "$HOME/installed-packages.tsv"

Get only package names and versions for quick diffs between baseline snapshots:

LC_ALL=C dpkg-query --show --showformat='${db:Status-Abbrev}\t${binary:Package}\t${Version}\n' | grep '^ii' | cut -f2- | sort > "$HOME/installed-baseline.txt"

When you only need the package count, count installed-state rows instead of counting every package record in dpkg’s database:

LC_ALL=C dpkg-query --show --showformat='${db:Status-Abbrev}\t${binary:Package}\n' | grep -c '^ii'

The command prints one number. The total depends on the system role and installed software:

1504

After saving two snapshots, compare them with diff:

diff -u "$HOME/installed-before.txt" "$HOME/installed-after.txt"

Review recent Ubuntu package changes from logs

Current package lists show what is installed now. When you need to know when software changed, inspect the local package logs. The current dpkg log is usually enough for recent install events:

grep " install " /var/log/dpkg.log | tail -n 20

Recent install entries include the timestamp, package name, architecture, previous state, and installed version:

2026-05-07 13:57:45 install curl:amd64 <none> 8.18.0-1ubuntu2.1
2026-05-07 13:57:45 install libfuse2t64:amd64 <none> 2.9.9-9build1

To include rotated logs, use zgrep and ignore missing compressed files:

zgrep -h " install " /var/log/dpkg.log* 2>/dev/null | tail -n 40

Log retention varies by system, so treat this as recent history rather than a complete lifetime package inventory.

Troubleshoot Ubuntu package list output

APT warns that apt list is not stable for scripts

If you pipe apt list --installed inside a script, APT can print this warning:

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

For interactive review, the warning is harmless. For automation, switch to dpkg-query with explicit fields:

LC_ALL=C dpkg-query --show --showformat='${db:Status-Abbrev}\t${binary:Package}\t${Version}\n' | grep '^ii' | cut -f2- | sort

dpkg list output uses unexpected header characters

Ubuntu 26.04 can show a newer dpkg --list header style depending on locale. If you need plain ASCII output for documentation, email, or older terminals, force the C locale:

LC_ALL=C dpkg --list | head -n 20

Removed packages still appear in a package audit

If a package shows the rc state, it was removed but still has conffiles. That state is useful during cleanup, but it should not be counted as an active package install.

LC_ALL=C dpkg-query --show --showformat='${db:Status-Abbrev}\t${binary:Package}\n' | grep '^rc' | cut -f2

For a clean installed-only inventory, keep the grep '^ii' filter from the earlier dpkg-query examples.

Snap or Flatpak apps are missing from dpkg output

This is expected. dpkg and dpkg-query report DEB packages only. Use snap list for Snap packages and flatpak list --app for Flatpak applications when those managers are installed.

Next Ubuntu package maintenance steps

Once your package list is deterministic, save the baseline before changing the system. If you plan to update first, take the final inventory after the update completes, then review leftover dependencies only when you understand why they are no longer required.

To see installed APT packages that currently have available upgrades, run:

apt list --upgradable

If the list is empty after package metadata is current, Ubuntu does not see pending upgrades from the configured APT sources.

Ubuntu package command references

Conclusion

A useful Ubuntu package inventory separates the quick APT view, the installed-state dpkg-query report, manual and automatic apt-mark flags, and any Snap or Flatpak apps managed outside APT. Save that baseline before updates or removals so each cleanup decision starts from current package state instead of memory.

Search LinuxCapable

Need another guide?

Search LinuxCapable for package installs, commands, troubleshooting, and follow-up guides related to what you just read.

Found this guide useful?

Support LinuxCapable to keep tutorials free and up to date.

Buy me a coffee Buy me a coffee

Before commenting, please review our Comments Policy.
Formatting tips for your comment

You can use basic HTML to format your comment. Useful tags currently allowed in published comments:

You type Result
<code>command</code> command
<strong>bold</strong> bold
<em>italic</em> italic
<blockquote>quote</blockquote> quote block

Got a Question or Feedback?

We read and reply to every comment - let us know how we can help or improve this guide.

Let us know you are human: