How to Search for Installed Packages in Linux

To check if a package is installed in Linux, use dpkg -l | grep packagename on Ubuntu/Debian or rpm -q packagename on Fedora/RHEL. To list all installed packages, use apt list --installed (Ubuntu/Debian) or dnf list installed (Fedora). To find which package provides a specific file already on your system, use dpkg -S /path/to/file or rpm -qf /path/to/file.

Knowing What Is Actually on Your System

A Linux system accumulates software over time — the base installation, packages you deliberately installed, dependencies pulled in automatically, and sometimes forgotten software from months or years ago that nobody remembers installing. Being able to quickly answer “is X installed?”, “what version of Y do I have?”, and “what does this file belong to?” is a fundamental skill for troubleshooting, auditing, and general system management.

Every distribution’s package manager maintains a complete database of what is installed — every package name, version, installation date, files it placed on the system, and its relationship to other packages. This article covers how to query that database thoroughly: checking specific packages, listing everything installed, searching by keyword, finding which package owns a particular file, and understanding package installation history.

Checking Installed Packages on Debian/Ubuntu (dpkg and apt)

dpkg -l: The Complete Package Database

dpkg -l lists every package dpkg knows about, including its installation status:

$ dpkg -l
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 22.08.8-1ubuntu4    amd64        query and manipulate user account information
ii  acl             2.3.1-3build1       amd64        Access control list utilities
ii  adduser         3.137ubuntu1        all          add and remove users and groups
ii  vim             2:9.1.0016-1ubuntu7 amd64        Vi IMproved - enhanced vi editor

Understanding the status codes:

  • ii — package is installed and configured correctly (the normal, healthy state)
  • rc — package was removed but configuration files remain
  • un — package is unknown/not installed
  • iU — package is unpacked but not configured (indicates a problem)
  • iF — installation failed

Checking a Specific Package with dpkg

$ dpkg -l | grep nginx
ii  nginx-common  1.24.0-2ubuntu7  all  small, powerful, scalable web/proxy server - common files
ii  nginx-core    1.24.0-2ubuntu7  amd64 nginx web/proxy server (standard version)

More precise checking with dpkg -s (status):

$ dpkg -s nginx-core
Package: nginx-core
Status: install ok installed
Priority: optional
Section: httpd
Installed-Size: 1234
Maintainer: Ubuntu Developers
Architecture: amd64
Version: 1.24.0-2ubuntu7

If not installed:

$ dpkg -s nonexistent-package
dpkg-query: package 'nonexistent-package' is not installed and no information is available

Checking installed status in a script (exit code approach):

if dpkg -s nginx-core &> /dev/null; then
    echo "nginx-core is installed"
else
    echo "nginx-core is NOT installed"
fi

apt list –installed: The Modern Approach

$ apt list --installed
Listing... Done
accountsservice/noble,now 22.08.8-1ubuntu4 amd64 [installed]
acl/noble,now 2.3.1-3build1 amd64 [installed]
adduser/noble,now 3.137ubuntu1 all [installed]
vim/noble,now 2:9.1.0016-1ubuntu7 amd64 [installed,automatic]

The [installed,automatic] tag shows packages installed automatically as dependencies (vs. [installed] for manually requested packages).

Filter for a specific package:

$ apt list --installed | grep nginx
nginx-common/noble,now 1.24.0-2ubuntu7 all [installed]
nginx-core/noble,now 1.24.0-2ubuntu7 amd64 [installed]

Check a specific package directly:

$ apt list --installed nginx-core

Counting Installed Packages

$ dpkg -l | grep '^ii' | wc -l
2134

$ apt list --installed 2>/dev/null | wc -l
2135

Listing Only Manually Installed Packages

Distinguishing what you explicitly installed from what came as a dependency:

$ apt-mark showmanual
vim
git
curl
docker-ce
nginx-core
$ apt-mark showauto | wc -l
1876    # Packages pulled in automatically as dependencies

This distinction matters when cleaning up a system — you generally want to keep manually installed packages and can safely remove unused automatic ones with apt autoremove.

Checking Installed Packages on Fedora/RHEL (rpm and dnf)

rpm -qa: List All Installed Packages

$ rpm -qa
accountsservice-22.08.8-1.fc40.x86_64
acl-2.3.1-4.fc40.x86_64
adwaita-icon-theme-45.0-1.fc40.noarch
vim-enhanced-9.1.0356-1.fc40.x86_64

Sort alphabetically for easier reading:

$ rpm -qa | sort

Count installed packages:

$ rpm -qa | wc -l
1876

Checking a Specific Package with rpm

$ rpm -q nginx
nginx-1.24.0-1.fc40.x86_64

If not installed:

$ rpm -q nonexistent-package
package nonexistent-package is not installed

Detailed information about an installed package:

$ rpm -qi nginx
Name        : nginx
Version     : 1.24.0
Release     : 1.fc40
Architecture: x86_64
Install Date: Mon 17 Feb 2026 09:22:15 AM UTC
Group       : Unspecified
Size        : 2345678
License     : BSD-2-Clause
Signature   : RSA/SHA256, Mon 10 Feb 2026 08:00:00 AM UTC
Source RPM  : nginx-1.24.0-1.fc40.src.rpm
Build Date  : Mon 10 Feb 2026 08:00:00 AM UTC
Summary     : A high performance web server and reverse proxy server

Checking installed status in a script:

if rpm -q nginx &> /dev/null; then
    echo "nginx is installed"
else
    echo "nginx is NOT installed"
fi

dnf list installed: The DNF Approach

$ dnf list installed
Installed Packages
accountsservice.x86_64      22.08.8-1.fc40      @fedora
acl.x86_64                  2.3.1-4.fc40        @updates
vim-enhanced.x86_64         9.1.0356-1.fc40     @updates

Filter for a specific package:

$ dnf list installed | grep nginx
nginx.x86_64                 1.24.0-1.fc40       @updates
nginx-filesystem.noarch      1.24.0-1.fc40       @updates

Check a specific package directly:

$ dnf list installed nginx

If not installed, dnf list installed nginx returns an error indicating no matching packages, which is itself useful confirmation.

Finding Which Package Provides a File

A common troubleshooting task: you found a file on your system and want to know which package installed it — useful for understanding what depends on it, checking its version, or verifying its integrity.

On Debian/Ubuntu with dpkg

$ dpkg -S /usr/bin/nginx
nginx-core: /usr/bin/nginx

$ dpkg -S /etc/nginx/nginx.conf
nginx-common: /etc/nginx/nginx.conf

$ dpkg -S /usr/bin/python3
libc6-dev:amd64, python3.12-minimal: /usr/bin/python3

Sometimes multiple packages match if the file path is shared or ambiguous.

If the file was not installed by any package (perhaps you created it, or a script generated it):

$ dpkg -S /home/sarah/myfile.txt
dpkg-query: no path found matching pattern /home/sarah/myfile.txt

On Debian/Ubuntu with apt-file (for files NOT currently installed)

dpkg -S only searches currently installed packages. To find which package (installed or not) would provide a specific file, use apt-file:

$ sudo apt install apt-file
$ sudo apt-file update
$ apt-file search /usr/bin/convert
imagemagick-6.q16: /usr/bin/convert-im6.q16

This is invaluable when you get a “command not found” error and want to know which package to install to get that command.

On Fedora/RHEL with rpm

$ rpm -qf /usr/bin/nginx
nginx-1.24.0-1.fc40.x86_64

$ rpm -qf /etc/nginx/nginx.conf
nginx-1.24.0-1.fc40.x86_64

If the file is not owned by any package:

$ rpm -qf /home/sarah/myfile.txt
file /home/sarah/myfile.txt is not owned by any package

On Fedora/RHEL with dnf provides (for files NOT currently installed)

$ dnf provides /usr/bin/convert
ImageMagick-6.9.12.98-1.fc40.x86_64 : An X application for displaying and manipulating images
Repo        : fedora
Matched from:
Filename    : /usr/bin/convert

This works even if the package is not installed — it searches the repository metadata to find which available package would provide the file.

Listing Files Installed by a Package

The reverse operation: given a package name, list every file it installed on the system.

On Debian/Ubuntu

$ dpkg -L nginx-core
/.
/etc
/etc/init.d
/etc/init.d/nginx
/etc/logrotate.d
/etc/logrotate.d/nginx
/usr
/usr/sbin
/usr/sbin/nginx
/usr/share
/usr/share/doc
/usr/share/doc/nginx-core

For a package not yet installed, inspect a downloaded .deb file:

$ dpkg -c downloaded_package.deb

On Fedora/RHEL

$ rpm -ql nginx
/etc/logrotate.d/nginx
/etc/nginx
/etc/nginx/conf.d
/etc/nginx/nginx.conf
/usr/lib/systemd/system/nginx.service
/usr/sbin/nginx

For a package file not yet installed:

$ rpm -qlp downloaded_package.rpm

Searching for Packages by Description or Keyword

Sometimes you know roughly what a package does but not its exact name — searching the package database by keyword finds candidates.

On Debian/Ubuntu

Search installed packages by keyword (name or description):

$ dpkg -l | grep -i "text editor"
ii  vim  2:9.1.0016-1ubuntu7  amd64  Vi IMproved - enhanced vi editor
ii  nano 7.2-2ubuntu0.1       amd64  small, friendly text editor inspired by Pico

Search all available packages (not just installed) by keyword:

$ apt search "text editor"
$ apt-cache search "text editor"    # Older equivalent

On Fedora/RHEL

$ dnf list installed | grep -i editor
$ dnf search "text editor"

Checking Package Installation Date and History

On Debian/Ubuntu: The dpkg Log

$ grep " install " /var/log/dpkg.log | tail -20
2026-02-15 09:22:15 install nginx-common:all 1.24.0-2ubuntu7
2026-02-15 09:22:16 install nginx-core:amd64 1.24.0-2ubuntu7
2026-02-16 14:30:02 install vim:amd64 2:9.1.0016-1ubuntu7

Check when a specific package was installed:

$ grep "install nginx" /var/log/dpkg.log

Historical dpkg logs (compressed, older entries):

$ zgrep "install nginx" /var/log/dpkg.log.*.gz

Using apt history:

$ cat /var/log/apt/history.log | grep -A2 "Install: nginx"

On Fedora/RHEL: The dnf/rpm History

$ dnf history
ID     | Command line                     | Date and time    | Action(s)      | Altered
------------------------------------------------------------------------------
    45 | install nginx                    | 2026-02-15 09:22 | Install        |    3
    44 | update                           | 2026-02-14 08:00 | Update         |   15
    43 | install vim                      | 2026-02-10 14:30 | Install        |    1

View details of a specific transaction:

$ dnf history info 45

Installation date from rpm database directly:

$ rpm -q --queryformat '%{INSTALLTIME:date}\n' nginx
Mon 15 Feb 2026 09:22:15 AM UTC

List all packages sorted by install date:

$ rpm -qa --last | head -20
nginx-1.24.0-1.fc40.x86_64          Mon 15 Feb 2026 09:22:15 AM UTC
vim-enhanced-9.1.0356-1.fc40.x86_64  Mon 10 Feb 2026 14:30:02 PM UTC

rpm -qa --last is one of the most useful commands for understanding recent system changes — it shows every installed package in reverse chronological order, immediately revealing what was installed recently.

Checking Package Dependencies

What Does This Package Need? (Dependencies)

Debian/Ubuntu:

$ apt-cache depends nginx-core
nginx-core
  Depends: libc6
  Depends: libpcre2-8-0
  Depends: libssl3
  Depends: zlib1g
  Depends: nginx-common

Fedora/RHEL:

$ rpm -qR nginx
libc.so.6()(64bit)
libpcre2-8.so.0()(64bit)
libssl.so.3()(64bit)
libz.so.1()(64bit)

What Depends on This Package? (Reverse Dependencies)

Debian/Ubuntu:

$ apt-cache rdepends nginx-common
nginx-common
Reverse Depends:
  nginx-core
  nginx-full
  nginx-light

Fedora/RHEL:

$ dnf repoquery --whatrequires nginx-common

Reverse dependency checking is essential before removing a package — it tells you what else on the system relies on it, preventing accidental breakage.

Verifying Package Integrity

Sometimes you want to confirm that installed files match what the package originally provided — useful for detecting corruption or unauthorized modification.

On Debian/Ubuntu

$ sudo apt install debsums     # Not installed by default
$ debsums nginx-core
/usr/sbin/nginx                                                     OK
/usr/share/doc/nginx-core/changelog.Debian.gz                       OK

debsums compares installed file checksums against the package’s recorded checksums.

On Fedora/RHEL

$ rpm -V nginx

No output means everything matches. Any output indicates discrepancies:

$ rpm -V nginx
S.5....T.  c /etc/nginx/nginx.conf

The character codes indicate what changed: S (size), 5 (checksum/MD5), T (timestamp), and others. The c marks it as a configuration file (expected to be modified by administrators, so this discrepancy is often normal and not concerning).

Practical Scenarios

Scenario 1: “Is Docker Installed?”

# Ubuntu/Debian
$ dpkg -l | grep docker
$ which docker

# Fedora
$ rpm -qa | grep docker
$ which docker

Scenario 2: “What Package Provides This Command?”

You run a command and get “command not found” — find which package to install:

# Ubuntu/Debian (requires apt-file)
$ apt-file search bin/convert
imagemagick-6.q16: /usr/bin/convert-im6.q16

# Fedora
$ dnf provides '*/convert'

Scenario 3: “What Did I Install Recently?”

# Ubuntu/Debian
$ grep " install " /var/log/dpkg.log | tail -20

# Fedora
$ rpm -qa --last | head -20

Scenario 4: “Can I Safely Remove This Package?”

Before removing, check what depends on it:

# Ubuntu/Debian
$ apt-cache rdepends packagename
$ apt remove --dry-run packagename    # Preview what would happen

# Fedora
$ dnf repoquery --whatrequires packagename
$ dnf remove packagename --assumeno   # Preview without removing

Scenario 5: “What Version Is Installed vs. Available?”

# Ubuntu/Debian
$ apt-cache policy nginx-core
nginx-core:
  Installed: 1.24.0-2ubuntu7
  Candidate: 1.24.0-2ubuntu7

# Fedora
$ dnf list nginx
Installed Packages
nginx.x86_64    1.24.0-1.fc40    @updates

Quick Reference: Package Query Commands

Debian/Ubuntu

Task Command
List all installed packages dpkg -l or apt list --installed
Check specific package dpkg -l | grep name or dpkg -s name
Package status details dpkg -s name
Files installed by package dpkg -L name
Which package owns a file dpkg -S /path/to/file
Search for uninstalled package by file apt-file search filename
Search available packages apt search keyword
Package dependencies apt-cache depends name
Reverse dependencies apt-cache rdepends name
Installation history grep install /var/log/dpkg.log
Verify package integrity debsums name
Manually installed packages apt-mark showmanual

Fedora/RHEL

Task Command
List all installed packages rpm -qa or dnf list installed
Check specific package rpm -q name
Package status details rpm -qi name
Files installed by package rpm -ql name
Which package owns a file rpm -qf /path/to/file
Search for uninstalled package by file dnf provides /path/to/file
Search available packages dnf search keyword
Package dependencies rpm -qR name
Reverse dependencies dnf repoquery --whatrequires name
Installation history rpm -qa --last or dnf history
Verify package integrity rpm -V name

Conclusion: Complete Visibility Into Your System

Every Linux package manager maintains a comprehensive, queryable record of exactly what is installed, when, and how everything relates. This is a level of system transparency that many other operating systems lack — you can always answer “what is on this system and why” with precision.

The essential commands to remember: dpkg -l or rpm -qa for the complete package list, dpkg -S or rpm -qf for finding which package owns a file, and apt list --installed or dnf list installed for the modern interface to the same information. Combined with dependency checking (apt-cache rdepends, dnf repoquery --whatrequires) before removing packages, you have everything needed to understand, audit, and confidently manage the software on any Linux system.

Hot this week

C++ Performance Profiling and Optimization Techniques

Master C++ performance optimization. Learn how to profile code, eliminate bottlenecks, leverage CPU caches, use Google Benchmark, and apply modern C++ techniques for maximum speed.

Implementing Design Patterns in Modern C++: A Complete Guide

Discover how modern C++ (C++11/14/17/20) revolutionizes classic GoF design patterns. Learn to write safer, cleaner, and more efficient code using smart pointers, lambdas, concepts, and std::variant.

SIMD Programming in C++: A Comprehensive Guide to Vectorization

SIMD (Single Instruction, Multiple Data) programming in C++ is...

Writing Cache-Friendly C++ Code

Learn to write cache-friendly C++ code — understand CPU caches, cache lines, spatial and temporal locality, data-oriented design, struct layout, false sharing, and how to measure cache performance.

Understanding Undefined Behavior in C++

Master C++ undefined behavior — learn what it is, the most dangerous forms (signed overflow, null dereference, data races, UB in templates), how compilers exploit it, and how to detect and eliminate it.

Topics

C++ Performance Profiling and Optimization Techniques

Master C++ performance optimization. Learn how to profile code, eliminate bottlenecks, leverage CPU caches, use Google Benchmark, and apply modern C++ techniques for maximum speed.

Implementing Design Patterns in Modern C++: A Complete Guide

Discover how modern C++ (C++11/14/17/20) revolutionizes classic GoF design patterns. Learn to write safer, cleaner, and more efficient code using smart pointers, lambdas, concepts, and std::variant.

SIMD Programming in C++: A Comprehensive Guide to Vectorization

SIMD (Single Instruction, Multiple Data) programming in C++ is...

Writing Cache-Friendly C++ Code

Learn to write cache-friendly C++ code — understand CPU caches, cache lines, spatial and temporal locality, data-oriented design, struct layout, false sharing, and how to measure cache performance.

Understanding Undefined Behavior in C++

Master C++ undefined behavior — learn what it is, the most dangerous forms (signed overflow, null dereference, data races, UB in templates), how compilers exploit it, and how to detect and eliminate it.

CMake Mastery: Modern C++ Build Systems

Master CMake for modern C++ projects — learn targets, properties, find_package, FetchContent, generator expressions, testing with CTest, and professional project structure.

Building Cross-Platform C++ Applications

Learn to build cross-platform C++ applications — handle OS differences, use CMake, manage compiler quirks, abstract platform APIs, write portable code, and test on multiple targets.

Coroutines in C++20: Asynchronous Programming

Master C++20 coroutines — learn co_await, co_yield, co_return, promise types, awaitables, generators, and how to build async tasks and lazy sequences without callback hell.

Related Articles

Popular Categories