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 remainun— package is unknown/not installediU— 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.




