2

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?

  • 2
    I just want to add that it is definitely not a bug that dpkg -S doesn't follow symlinks. There are plenty of packages in which a symlink is installed in a different package than the target, with different meanings. /sbin/init -> /lib/systemd/systemd is installed by systemd-sysv, not systemd; /usr/include/asm is installed by gcc-multilib not whatever arch-specific package, etc. However, it does make sense that symlinks through /etc/alternatives should be followed. – o11c Oct 3 '14 at 6:27
  • 1
    @o11c I called it an issue on purpose although the original called ig a bug report. A suspect is not necessary a criminal :-). An extra dpkg option to follow symlinks would be nice though as that could more easily both show the package that install the symlink (if any) as well as the "real" target. Some more intelligent behaviour around symlinks managed by update-alternative would certainly be appropriate, especially as that command is part of the dpkg package. – Anthon Oct 3 '14 at 6:58
3

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

  • Better to use realpath than readlink -f, since not all versions of readlink support the -f flag, but realpath is going to DTRT if it exists. – o11c Oct 3 '14 at 6:20
  • @o11c Are there other version of readlink than the coreutils version? Or are you talking about old implementations (how old)? – Anthon Oct 3 '14 at 6:45
  • It's not specified by POSIX, and OSX and *BSD versions don't support it, or make it mean something completely different. – o11c Oct 3 '14 at 20:52
  • You don't need -n: $() already eats up trailing newlines. – Ciro Santilli 新疆改造中心法轮功六四事件 Aug 28 '15 at 8:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.