apt-file

Which package ships a file you have not installed

Updated 2026-08-26

apt-file searches Debian's record of which package contains which file. The record covers the whole archive rather than your disk, so it will name the package for a command nobody here has installed. dpkg -S reads the file lists dpkg wrote when it unpacked each package, and never sees past them.

The package is not part of a Debian install, so the first step is apt install apt-file. Installing it drops a fragment into /etc/apt/apt.conf.d/ asking apt to fetch the Contents index, and until the next update there is nothing on disk to search: a query before that point answers E: The cache is empty. You need to run "apt-file update" first.

A search then scans a few tens of megabytes and takes a second or so. dpkg -S answers in a few tens of milliseconds, so try it first on any file that might already be installed.

Sample files used on this page

Every example below was run against these files. Recreate them to follow along.

wanted.txt the batch of paths the -f examples look up, one per line: a command, a development header and a game, none of them installed here

/usr/bin/nslookup
/usr/include/zlib.h
/usr/games/cowsay
25 outputs, collapsed by default

Find the package that ships a file

apt-file reads Debian's index of which package contains which path, so it can answer for a package nobody has installed. dpkg -S works from the file lists on the disk, and is limited to what those cover.

Find the package for a command you do not have

apt-file search bin/ifconfig

The pattern does not have to be a whole path, which saves you from having to remember where Debian puts things. ifconfig moved to /usr/sbin in the /usr merge, and a fragment like bin/ifconfig finds it either side of that.

Show output
net-tools: /usr/sbin/ifconfig

Confirm dpkg cannot answer for a package you have not installed

dpkg -S /usr/sbin/ifconfig

dpkg -S searches the file lists dpkg wrote when it unpacked each package. net-tools is not installed here, so there is no list to find the path in, and the message says so rather than saying no package ships it.

Show output
dpkg-query: no path found matching pattern /usr/sbin/ifconfig

Search for an exact path

apt-file search /usr/games/cowsay

A leading / makes the pattern an absolute path. Use it when you know exactly where the file belongs.

Show output
cowsay: /usr/games/cowsay

Print only the package name

apt-file search -l bin/nslookup

-l (--package-only) drops the paths and de-duplicates, which is the form to use when the answer is going into apt install.

Show output
bind9-dnsutils

Find the package for a missing header file

apt-file search /usr/include/zlib.h

The reason a build fails with fatal error: zlib.h: No such file or directory is almost always a missing -dev package, and this is how to find out which one.

Show output
zlib1g-dev: /usr/include/zlib.h

Find the package that ships a systemd unit

apt-file search lib/systemd/system/cron.service

Unit files are packaged like any other file, so a unit named in a guide you are following can be traced back to the package that would install it. See systemd services.

Show output
cron: /usr/lib/systemd/system/cron.service

See what happens when nothing matches

apt-file search /usr/bin/definitely-not-a-real-file

No output, and an exit status of 1. A script can test for that rather than parsing the empty result.

Search for a file you do have

apt-file search /usr/bin/apt-file

apt-file never looks at your disk. It searches the archive index either way, so it will also name the package behind a file you already have.

Show output
apt-file: /usr/bin/apt-file

Control what the pattern matches

A pattern with no wildcards in it is matched as a substring of the whole path, which finds more than people expect.

See why a plain pattern matches too much

apt-file search /usr/bin/dig

/usr/bin/dig is a substring of /usr/bin/digikam and of six other paths, so seven packages answer and the command you wanted is the first line.

Show output
bind9-dnsutils: /usr/bin/dig
digikam: /usr/bin/digikam
digikam: /usr/bin/digitaglinktree
digitemp: /usr/bin/digitemp_DS9097
digitemp: /usr/bin/digitemp_DS9097U
digup: /usr/bin/digup
golang-golang-x-tools: /usr/bin/digraph
texlive-extra-utils: /usr/bin/digestif

Anchor a search to the end of the path

apt-file search -x 'bin/dig$'

-x (--regexp) treats the pattern as a regular expression, so $ pins it to the end of the path and the seven near-misses disappear. Leave the /usr off while you are at it. The index stores paths without their leading slash, so a pattern carrying one has to be compiled into an alternation of both forms and matched twice, which doubles the time the search takes.

Show output
bind9-dnsutils: /usr/bin/dig

Search for several commands at once

apt-file search -x 'bin/(ifconfig|route)$'

The alternation reads the index once where two searches would read it twice, and a pass is tens of megabytes.

Show output
net-tools: /usr/sbin/ifconfig
net-tools: /usr/sbin/route

Match a group of files with a regular expression

apt-file search -x 'share/cowsay/cows/[bc].*\.cow$'

Quote the pattern. $, * and [ are all meaningful to the shell, and an unquoted pattern is expanded against your working directory before apt-file ever sees it.

Show output
cowsay: /usr/share/cowsay/cows/bud-frogs.cow
cowsay: /usr/share/cowsay/cows/bunny.cow
cowsay: /usr/share/cowsay/cows/calvin.cow
cowsay: /usr/share/cowsay/cows/cheese.cow
cowsay: /usr/share/cowsay/cows/cock.cow
cowsay: /usr/share/cowsay/cows/cower.cow
cowsay-off: /usr/share/cowsay/cows/beavis.zen.cow
cowsay-off: /usr/share/cowsay/cows/bong.cow

Ignore case when you are unsure of the spelling

apt-file search -i games/COWSAY

-i (--ignore-case) matters most with fonts, icons and documentation, where capitalisation in the filename is not something anyone remembers.

Show output
cowsay: /usr/games/cowsay

Find every translation of a manual page

apt-file search --substring-match man8/ifconfig

--substring-match forces the substring behaviour even for a pattern containing wildcards, so nothing in it is treated as a glob or a regular expression.

Show output
manpages-es: /usr/share/man/es/man8/ifconfig.8.gz
manpages-ja: /usr/share/man/ja/man8/ifconfig.8.gz
manpages-pl: /usr/share/man/pl/man8/ifconfig.8.gz
manpages-ro: /usr/share/man/ro/man8/ifconfig.8.gz
manpages-tr: /usr/share/man/tr/man8/ifconfig.8.gz
manpages-zh: /usr/share/man/zh_CN/man8/ifconfig.8.gz
manpages-zh: /usr/share/man/zh_TW/man8/ifconfig.8.gz
net-tools: /usr/share/man/de/man8/ifconfig.8.gz
net-tools: /usr/share/man/fr/man8/ifconfig.8.gz
net-tools: /usr/share/man/man8/ifconfig.8.gz
net-tools: /usr/share/man/pt_BR/man8/ifconfig.8.gz

Look up a list of paths in one go

apt-file search -F -f wanted.txt

-f (--from-file) reads one pattern per line, and one pass over the index answers all of them. Pair it with -F (--fixed-string) when the lines are complete paths: without it each line is compiled into the same regular expression, which takes twice as long as the search itself.

Show output
bind9-dnsutils: /usr/bin/nslookup
cowsay: /usr/games/cowsay
zlib1g-dev: /usr/include/zlib.h

List what a package contains

The same index read the other way round: apt-file list is dpkg -L for a package you have not installed yet. show is a second name for the same action, as find is for search.

List the files a package would install

apt-file list cowsay | head -5

cowsay is not installed here. The listing comes from the archive index, so nothing is downloaded and nothing is unpacked.

Show output
cowsay: /usr/games/cowsay
cowsay: /usr/games/cowthink
cowsay: /usr/share/cowsay/cows/apt.cow
cowsay: /usr/share/cowsay/cows/bud-frogs.cow
cowsay: /usr/share/cowsay/cows/bunny.cow

Find the manual pages a package would give you

apt-file list cowsay | grep man

The listing is plain text, so grep narrows it. Note that snowman.cow matches too, which is the usual reason to anchor the pattern.

Show output
cowsay: /usr/share/cowsay/cows/snowman.cow
cowsay: /usr/share/man/man6/cowsay.6.gz
cowsay: /usr/share/man/man6/cowthink.6.gz

See what happens with a package that does not exist

apt-file list definitely-not-a-real-package

Nothing, and exit status 1. list matches the package name as a substring, so a typo that is a prefix of a real package will quietly list that one instead.

Check whether a downloaded .deb collides with anything

apt-file search -l -D cowsay_*.deb

-D (--from-deb) takes the file list out of a .deb that apt-get download cowsay left in the working directory, and searches the archive for every path in it. Only the package itself comes back, so no other package would have its files overwritten. Drop the -l to see which paths collided.

Show output
cowsay

Where the index comes from

apt-file searches a file called Contents, which apt downloads only because installing apt-file asked it to.

See what installing apt-file changed

dpkg -L apt-file | grep apt.conf

That one fragment adds the Contents indices to Acquire::IndexTargets. From then on, an ordinary apt update fetches them along with the package lists.

Show output
/etc/apt/apt.conf.d
/etc/apt/apt.conf.d/50apt-file.conf

Check the index is present before searching

apt-file list-indices

Ok against deb means there is something to search. Empty (code: 3) means the file was never downloaded, and every search will report The cache is empty until it is.

Show output
+-----------------+-----------------------------+-----------------+
| Index Name (-I) | DefaultEnabled (Apt config) | Index Status    |
+-----------------+-----------------------------+-----------------+
| deb             | <unset>                     | Ok              |
| udeb            | false                       | Empty (code: 4) |
| dsc             | false                       | Empty (code: 4) |
+-----------------+-----------------------------+-----------------+

Download the index

apt-file update 2>&1 | tail -1

Since apt-file 3.0 this runs apt-get update for you, restricted to the Contents indices, and the lines it prints before this one are the same Get: and Hit: lines that command gives. Running plain apt update keeps the index current too, so on a machine you update anyway this is only needed once.

Show output
Reading package lists...