119

I've read a lot about the realpath command and how it has been deprecated with readlink -f being now recommended.  I have also seen in some places that the reason why realpath was introduced was for the lack of such functionality in readlink and that once it was introduced, realpath was no longer needed and its support discontinued by most OS vendors.

The reason for my question is that I've also seen many people recommending readlink -f as a command "pretty much similar" to realpath, and that is what is bothering me, because no one elaborates on that "pretty much similar" part.  What are the actual differences?

3 Answers 3

119

There are several realpath commands around.

The realpath utility is a wrapper around the realpath library functions and has been reinvented many times.

Debian used to maintain a realpath package (separated from dwww since woody) which hasn't changed except regarding packaging and documentation since 2001, but has now been phased out. This utility was deprecated because there are now more standard alternatives (GNU readlink and soon GNU realpath), but at the time, GNU utilities didn't even have readlink at all. This implementation of realpath supports a few options to prevent symbolic link resolution or produce null-terminated output. BusyBox also includes its own realpath command (which takes no option).

GNU coreutils introduced a realpath command in version 8.15 in January 2012. This is a compatible replacement for BusyBox's and Debian's realpath, and also has many options in common with GNU readlink.

realpath has the same effect as readlink -f with GNU readlink. What distinguishes the two commands (or rather the various realpath commands from readlink -f) is the extra options that they support.

GNU realpath is not deprecated; it has the opposite problem: it's too new to be available everywhere. Debian used to omit GNU realpath from its coreutils package and stick with its own realpath. I don't know why, since GNU realpath should be a drop-in replacement. As of Debian jessie and Ubuntu 16.04, however, GNU realpath is used.

On Linux systems, at the moment, your best bet to canonicalize a path that may contain symbolic links is readlink -f.

BSD systems have a readlink command, with different capabilities from GNU readlink. In particular, BSD readlink does not have an option to canonicalize paths, it only traverses the symlink passed to it.

readlink, incidentally, had the same problem — it was also invented many times (not adding this utility when symbolic links were added to Unix was a regrettable omission). It has now stabilized in several implementations with many incompatible flags (in particular BSD vs. GNU).

5
  • 9
    readlink -f was in OpenBSD long before GNU. All of NetBSD, FreeBSD and OpenBSD now have readlink -f (your link even mentions it). realpath has been in FreeBSD and IRIX for a long time (don't know if it predates the one in Debian). HPUX and IRIX also have readlink, though not -f. The realpath package in Debian experimental is now the one from coreutils (as an experiment to see if it breaks things). The dwww realpath acts more like readlink -e while the GNU one like readlink -f so it's not a complete dropin replace Jun 11, 2014 at 8:22
  • 3
    realpath has been in FreeBSD since 2002. Before that, pwd was doing it (since 2000, pwd some-file would call realpath() on file). Debian has had a realpath package since 1996. The one on IRIX probably predates it though I found no evidence other than it was in IRIX 6.5 in 1998. OpenBSD added a -f to readlink in 1997. GNU added readlink in 2003 and it had -f from the start. Jun 11, 2014 at 9:09
  • 2
    Excellent summary thanks. Note a better bug for the request for debian to switch to the GNU variant is bugs.debian.org/730779 Even the existing realpath maintainer wants the switch to happen Jun 11, 2014 at 12:46
  • 1
    Awesome answer. Missed only references to RHEL implementation of realpath. Does anyone know if it is somehow different from the readlink -f version? Jun 11, 2014 at 12:50
  • 1
    @StéphaneChazelas Oh wow, lots of errors in my answers indeed. Thanks for pointing them out. Could you post a correct answer, and I'll delete mine? (Otherwise, I'll correct the errors, but it's more work to tack on to my long todo list…) Jun 11, 2014 at 18:05
34

tl;dr readlink -f will return 0 for a non-existent file in an existing directory whereas realpath returns 1. However, readlink -e will behave like realpath and return 1 for a non-existent file (see Editors Notes at end).

readlink -f

$ readlink -f non-existent-file
/home/user/non-existent-file
$ echo $?
0

readlink -e

$ readlink -e non-existent-file
$ echo $?
1

realpath

$ realpath non-existent-file
non-existent-file: No such file or directory
$ echo $?
1

readlink -f with non-existent directory

readlink -f behavior varies depending upon which part of the path does not exist.

$ readlink -f /tmp/non-existent-dir/foo
$ echo $?
1

realpath with non-existent directory

$ realpath /tmp/non-existent-dir/foo
$ echo $?
1

Availablity

readlink is already installed within most Linux distributions. Whereas, realpath is also becoming more often already installed as realpath has been rolled into GNU Coreutils (in prior years, it was it's own separate package).

In summary

If you want to replace calls to realpath ... then use readlink -e ....
However, realpath is becoming more widely distributed, so it's not unreasonable to expect realpath to be installed.

MMV readlink implementations vary widely.
MMV realpath availability in a default Linux installation varies somewhat more than readlink.


Tested with readlink (GNU coreutils) 8.21 and realpath version 1.19 on Ubuntu 16.


Editors Notes

3
  • 5
    I upvoted this answer but I'd suggest clarifying that this refers to the Debian version of realpath. The GNU version of realpath behaves the same as readlink -f. Oct 5, 2016 at 15:31
  • 3
    Can confirm that this doesn't work on MacOS High Sierra.
    – FilBot3
    Sep 18, 2018 at 21:07
  • 1
    Just in case, some versions of readlink may not output the path of non-existing entity with any of paths missing in the middle even with -f option stated (e.g. GNU coreutils 8.32) and will return code 1. Busybox versions also differ and very.
    – Artfaith
    Jul 16, 2023 at 2:30
2

As stated in other responses, the functionality of readlink -f or readlink -e (depending on the distribution) can be equivalent to that of realpath. However, realpath the utility is not equivalent to readlink. E.g., readlink can read/retrieve the contents of (the literal text in) a symbolic link file:

> ln -s "I am cold" slfile
> readlink slfile
I am cold

which realpath cannot do.

A symbolic link file, after all, is a text file interpreted as a "recipe" to move about the directory/file hierarchy. But it is still a text file. For example, its contents (what readlink returns) should be possible to be manipulated with sed -i '...' slfile -- in fact, option --follow-symlinks is to force sed -i to follow symlinks. I write "should" because in my current setup (OpenSuSe 15.3 default, GNU sed 4.4, GNU bash version 4.4.23(1)) this malfunctions: sed -i without the --follow-symlinks option still wants to follow as a path the contents of a symlink file.

1
  • Welcome to the site, and thank you for your contribution. However, concerning your statement 'A symbolic link file, after all, is a text file interpreted as a "recipe" to move about the directory/file hierarchy': This used to be the case in old Kernel implementations, but nowadays things are a little more complex (see "fast symlinks").
    – AdminBee
    Oct 29, 2021 at 13:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .