For many years I've been irritated by Linux's symbolic links - particularly the
useful but incredibly annoying /etc/alternatives/ arrangement. This is
meant to allow different packages to install the same binaries - not usually at
the same time, but
/etc/alternatives/java is meant to be a link to
whichever version of Java you have installed. A reasonably good idea, but the
problem is this:
$ which java /usr/bin/java $ ls -l /usr/bin/java lrwxrwxrwx. 1 root root 22 Dec 6 2020 /usr/bin/java -> /etc/alternatives/java
The problem is ... you still don't know which
java you have. You have to
go 'round again:
$ ls -l /etc/alternatives/java lrwxrwxrwx. 1 root root 63 May 17 09:33 /etc/alternatives/java -> /usr/lib/jvm/java-11-openjdk-220.127.116.11.9-2.fc33.x86_64/bin/java
As it turns out, this is the actual binary - but in this context you can't actually tell (it could be another link). There are better ways to check, in the form of a couple utilities:
readlink. The former provides more information, but most of the time I just want the final binary target, and the latter is better for that.
$ namei $(which java) f: /usr/bin/java d / d usr d bin l java -> /etc/alternatives/java d / d etc d alternatives l java -> /usr/lib/jvm/java-11-openjdk-18.104.22.168.9-2.fc33.x86_64/bin/java d / d usr d lib d jvm d java-11-openjdk-22.214.171.124.9-2.fc33.x86_64 d bin - java
I'm not trying to give you a full description of these things: read the (short) man pages if you want the full details. But
namei traces the links back to their origin, telling you when it finds a f file, d directory, or l link.
readlink defaults to only disambiguating the first link: to get it to follow all further links, use the -f option. For Mac users, Darwin has
readlink but it is itself a link to
stat and doesn't support -f. If you want that,
brew install coreutils and use the
greadlink command ("g" for "GNU").
$ readlink -f $(which java) /usr/lib/jvm/java-11-openjdk-126.96.36.199.9-2.fc33.x86_64/bin/java
I use this command a LOT, including assigning its output to a variable to capture the target binary.