Why dpkg -S May Not Find /usr/bin/bash on Ubuntu

· linux · #ubuntu #debian #dpkg #apt #packages #usr-merge

Background

When working on Ubuntu or Debian systems, it is common to ask a simple question:

Which package owns this executable?

For example, you may try:

dpkg -S /usr/bin/bash
dpkg -S /usr/bin/dash

Surprisingly, these commands may return no result, even though both commands clearly exist on the system:

which bash
which dash

The output may be:

/usr/bin/bash
/usr/bin/dash

Even more confusingly, searching Ubuntu’s package contents website may also fail when using the /usr/bin/... path, for example:

https://packages.ubuntu.com/search?mode=exactfilename&searchon=contents&keywords=%2Fusr%2Fbin%2Fbash

This looks contradictory at first, but the reason is the interaction between package file lists, $PATH, and the merged /usr filesystem layout.


The Short Answer

On many modern Ubuntu systems, /bin is a symbolic link to /usr/bin:

/bin -> /usr/bin

So these two paths may refer to the same executable:

/bin/bash
/usr/bin/bash

However, dpkg records the file path that the package declares in its package file list. For historical and compatibility reasons, packages such as bash and dash may still be registered as owning:

/bin/bash
/bin/dash

not:

/usr/bin/bash
/usr/bin/dash

Therefore, this may fail:

dpkg -S /usr/bin/bash

but this should work:

dpkg -S /bin/bash

Typical output:

bash: /bin/bash

And similarly:

dpkg -S /bin/dash

Typical output:

dash: /bin/dash

What dpkg -S Actually Does

dpkg -S searches the local Debian package database for a file path.

For example:

dpkg -S /bin/bash

asks:

Which installed package registered /bin/bash in its file list?

It does not ask:

Which package owns the inode that /usr/bin/bash eventually resolves to?

That distinction matters.

dpkg -S performs a package database lookup based on recorded path names. It does not automatically canonicalize paths through symbolic links, and it does not automatically treat /bin/bash and /usr/bin/bash as interchangeable strings.

So if the package database records:

/bin/bash

then searching for:

/usr/bin/bash

may not match, even if both paths point to the same executable at runtime.


Why which dash Shows /usr/bin/dash

The which command is different from dpkg -S.

which searches executable names through the directories listed in $PATH.

For example, a typical Ubuntu $PATH may look like this:

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Notice that /usr/bin appears before /bin.

When you run:

which dash

which checks the directories in $PATH order and finds:

/usr/bin/dash

Because /bin is commonly a symbolic link to /usr/bin, /bin/dash and /usr/bin/dash are effectively the same executable. But which only reports the first matching path it finds through $PATH.

This is why the following two facts can both be true:

which dash

outputs:

/usr/bin/dash

while:

dpkg -S /bin/dash

outputs:

dash: /bin/dash

They are answering different questions.


Why Ubuntu’s Package Website May Not Find /usr/bin/bash

Ubuntu’s package content search behaves similarly to dpkg -S in this case: it searches package content indexes.

If the package content index records the file as:

/bin/bash

then an exact filename search for:

/usr/bin/bash

may fail.

Instead, search for:

/bin/bash

or:

/bin/dash

This applies especially when using exact filename mode on:

https://packages.ubuntu.com/

The website is not doing a live filesystem lookup on your machine. It is searching package metadata. Package metadata may preserve historical paths such as /bin, even when installed systems expose the same files through /usr/bin because of merged /usr.


Merged /usr: The Source of the Confusion

Historically, Unix-like systems separated directories such as:

/bin
/sbin
/lib
/usr/bin
/usr/sbin
/usr/lib

The original idea was that /bin and /sbin contained essential binaries needed early during boot, while /usr could be a separate filesystem.

Modern Linux systems usually no longer need that strict separation. Many distributions have moved toward a merged /usr layout, where traditional top-level directories are symbolic links into /usr:

/bin  -> /usr/bin
/sbin -> /usr/sbin
/lib  -> /usr/lib

This simplifies the filesystem layout, but it creates a visible difference between:

  • the runtime path that shell tools may find;
  • the historical path recorded in package metadata.

That is exactly what happens with bash and dash.


How to Verify on Your Machine

You can inspect the layout with:

ls -ld /bin /usr/bin

If /bin is a symbolic link, you may see something like:

lrwxrwxrwx 1 root root 7 ... /bin -> usr/bin

Then compare the two paths:

ls -li /bin/bash /usr/bin/bash
ls -li /bin/dash /usr/bin/dash

If they point to the same file, the inode information should match.

You can also resolve the canonical path:

realpath /bin/bash
realpath /usr/bin/bash
realpath /bin/dash
realpath /usr/bin/dash

And then query package ownership using the path recorded by the package database:

dpkg -S /bin/bash
dpkg -S /bin/dash

A Practical Debugging Rule

When dpkg -S fails for a path under /usr/bin, try the equivalent traditional path under /bin:

dpkg -S /usr/bin/name
dpkg -S /bin/name

Similarly, for system administration tools, try both:

dpkg -S /usr/sbin/name
dpkg -S /sbin/name

For libraries, the same idea may apply to /lib and /usr/lib, depending on the architecture-specific directory layout.


Command Comparison

Command What it searches Important detail
which dash $PATH directories Reports the first executable found in runtime search order
command -v dash Shell command resolution Usually preferred in shell scripts over which
dpkg -S /bin/dash Local package database Searches recorded package file paths
Ubuntu package contents search Remote package content index Searches package metadata, not your live filesystem
realpath /usr/bin/dash Filesystem path resolution Follows symbolic links and prints the canonical path

Conclusion

The confusing result comes from asking different tools different questions.

which dash answers:

Where does my shell environment find an executable named dash?

dpkg -S /usr/bin/dash answers:

Which installed package recorded exactly this path in its file list?

On a merged /usr Ubuntu system, /bin/dash and /usr/bin/dash may refer to the same executable, but package metadata may still record the traditional /bin/dash path.

So the reliable command is:

dpkg -S /bin/dash
dpkg -S /bin/bash

And when using Ubuntu’s package website, search for the package metadata path, such as /bin/bash, rather than only the runtime path reported by which.