What's the difference between "realpath" and "readlink -f"
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).
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 note 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 installed within most Linux distributions. Whereas, realpath
must often be explicitly installed.
In summary
If you want to replace calls to realpath ...
then use readlink -e ...
.
MMV readlink
implementations vary widely.
Tested with readlink (GNU coreutils) 8.21 and realpath version 1.19 on Ubuntu 16.
(Ed.: @AnthonyGeoghegan wrote "this refers to the Debian version of realpath
. The GNU version of realpath
behaves the same as readlink -f
")
(Ed.: @FilBot3 wrote "this doesn't work on MacOS High Sierra")