How to find the package that installed a comand, if “dpkg -S” finds no path because the command is a symlink

dpkgrenamesymlink

While I was writing up a tag information for , I tried to look up with which package the rename command was installed. I ran the usual dpkg -S (also mentioned in this question):

$ which rename
/usr/bin/rename
$ dpkg -S $(!!)
dpkg-query: no path found matching pattern /usr/bin/rename

I normally don't install commands by hand in /usr/bin, and on the other machines I have access to, rename is installed as well. My first suspicion was that this command was copied there in some post-install step of some package.

Then I did an ls -l /usr/bin/rename and found that the rename command did happen to be a link. I tried dpkg -S on the link target (/etc/alternatives/rename), but dpkg -S /etc/alternatives/rename did not give a package name either.

After some further searching I found that real executable target of that link chain is /usr/bin/prename and there is a bug report for dpkg -S behaviour of not following symlinks. That report is from 2003 and I could not find any option to follow symlinks for dpkg and that issue doesn't seem likely to be resolved.

How can I easily find the package that contains the "real" executable in case the command is a symlink?

Best Answer

You can use readlink to print where a link points to. The argument to readlink without options has to be a link, if you pass it a file, it will not print anything. The -f option for readlink, from the coreutils package, recursively follows links and prints the filename even if the argument already is a file.

If you do (-n supresses the newline at the end of the readlink output):

dpkg -S "$(readlink -fn "$(which rename)")"

You will get as answer:

perl: /usr/bin/prename

that a link was followed is in this case clear from the prename, but this is not guaranteed to be the case (e.g. if a link was pointing to an executable rename in a directory that is not in your $PATH).

As @011c indicated, and if you have it installed, you can use realpath as alternative to readlink -f

Related Question