realpath is a pathname cannonicalizer. It is included in the [[POSIX]] [[Single UNIX Specification]]. There are many variations with many licenses including in different operating systems and distros, although most of them are written in [[3. Reference/Software/Programming Languages/C|C]]. > **realpath**() expands all symbolic links and resolves references to _/./_, _/../_ and extra '/' characters in the null-terminated string named by _path_ to produce a canonicalized absolute pathname. The resulting pathname is stored as a null-terminated string, up to a maximum of **PATH_MAX** bytes, in the buffer pointed to by _resolved_path_. The resulting path will have no symbolic link, _/./_ or /../ components. > > If _resolved_path_ is specified as NULL, then **realpath**() uses [malloc(3)](https://www.man7.org/linux/man-pages/man3/malloc.3.html) to allocate a buffer of up to **PATH_MAX** bytes to holdthe resolved pathname, and returns a pointer to this buffer. The caller should deallocate this buffer using [free(3)](https://www.man7.org/linux/man-pages/man3/free.3.html). # Notability It is very useful, but only up until relatively recently has it been available on most POSIX platforms. This vexed me for years and so one day in [[2023]] I sat down to figure out where it came from and why it wasn't always present. The `realpath()` [[C]] function *did* exist all this time, just not the commandline utility. # Usage ## GNU Core Utils ``` Usage: realpath [OPTION]... FILE... Print the resolved absolute file name; all but the last component must exist -e, --canonicalize-existing all components of the path must exist -m, --canonicalize-missing no path components need exist or be a directory -L, --logical resolve '..' components before symlinks -P, --physical resolve symlinks as encountered (default) -q, --quiet suppress most error messages --relative-to=DIR print the resolved path relative to DIR --relative-base=DIR print absolute paths unless paths below DIR -s, --strip, --no-symlinks don't expand symlinks -z, --zero end each output line with NUL, not newline --help display this help and exit --version output version information and exit GNU coreutils online help: <https://www.gnu.org/software/coreutils/> Full documentation <https://www.gnu.org/software/coreutils/realpath> or available locally via: info '(coreutils) realpath invocation' ``` ## BSD Core Utils Including [[Userspace Toolchains#BSD Core Utils|BSD Core Utils for Linux]], [[OpenBSD]], and [[FreeBSD]]. ``` usage: realpath [-q] [path ...] ``` ## NetBSD Core Utils ``` usage: realpath [-Eeq] [path ...] ``` `-e` works the same as [[#GNU Core Utils]], while `-E` (default) is the inverse to allow overriding it. # Philosophy # OS Support ## POSIX `realpath` became part of the BASE SUS specification with Issue 5 in 1997. It is part of both of the userspace tools and [libc function list](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdlib.h.html#tag_13_50). ## Linux Due to a variety of reasons (most of which I am unclear on), `realpath` was not widespread on Linux systems until well into the 2010s. `realpath` was finally added to [GNU Coreutils](https://www.gnu.org/software/coreutils/manual/html_node/realpath-invocation.html) in 2012, this caused other versions common in the Linux community to become deprecated. However, there have been large gaps in time where there was no `realpath` command in popular Linux distros even until around 2014, so answers online are often ignorant of it. - [[Debian]] - Custom-built command maintained by Debian until 2012 when it was deprecated, leading to a ton of confusion - Switched to GNU version around 2014 - GNU Core Utils - Introduced a `realpath` command in 2012, but wasn't widely adopted for a couple of years - [[Busybox]] - Has a simplified BSD-like version of `realpath` ## BSD - [[FreeBSD]] - [command](https://man.freebsd.org/cgi/man.cgi?query=realpath&apropos=0&sektion=0&manpath=FreeBSD+13.2-RELEASE+and+Ports&arch=default&format=html) since [2001](https://www.freebsd.org/releases/4.3R/announce/) - only takes `-q` option to silence warnings, no other options - [function](https://man.freebsd.org/cgi/man.cgi?query=realpath&sektion=3&apropos=0&manpath=FreeBSD+13.2-RELEASE+and+Ports) since May 26th, 1994 - Inherited directly from 4.4BSD-Lite "bin sources" in `stdlib.h` - commit `4b88c807ea9c629dc5691abc7e3cac9ea0d776dd` - [[NetBSD]] - [command](https://man.netbsd.org/realpath.1) since February 2nd, [2020](https://www.netbsd.org/changes/changes-10.0.html) - Ported from FreeBSD, but modified to add `-e` and `-E` - [commit](https://github.com/NetBSD/src/commit/771c425869ea044e9674e109d7dba0c41c86a181) `771c425869ea044e9674e109d7dba0c41c86a181` - [function](https://man.netbsd.org/realpath.3) since May 17th, 1994 - Ported from 4.4BSD-Lite - [commit](https://github.com/NetBSD/src/commit/1c98b23af186a2bae730c49d1d9baf0861b51750) `1c98b23af186a2bae730c49d1d9baf0861b51750` - NetBSD also [had](https://www.netbsd.org/releases/formal-3/NetBSD-3.0.1.html) the `intercept_realpath` [function](https://github.com/NetBSD/src/commit/9d002bc47df6b5d5b7d548b36af94452981044b2#diff-f8cffa89fe19ac3c89a0b9fc051221d76f275245680d8ab8a86f70d57360b9f2R995), but was removed along with `systrace` on December 31st, 2007 in [commit](https://github.com/NetBSD/src/commit/2ecdf58c2c9f227031628cbec276d336f29dbb4e) `2ecdf58c2c9f227031628cbec276d336f29dbb4e` - [[DragonFly BSD]] - [command](https://leaf.dragonflybsd.org/cgi/web-man?command=realpath) since v1 - [function](https://man.dragonflybsd.org/?command=realpath&section=3) since v1 - Forked from FreeBSD after the these features already existed - Has identical options and behaviour to the FreeBSD version - [[OpenBSD]] - [command](https://man.openbsd.org/realpath.1) since [2022](https://www.openbsd.org/71.html) - [function](https://man.openbsd.org/realpath.3) since at least 2012 - Inherited from 4.4BSD - OpenBSD started as a form of NetBSD v1 in 1996 and probably acquired it then ## Solaris [[Solaris]] appears to be the birthplace of `realpath`. Nearly every subsequent implementation mentions it by name. While `realpath` seems to have entered the POSIX zeitgeist in the mid 90s, reference manuals for SunOS with a "last changed" date of 1987 list `realpath`. The 4.2BSD and 4.3BSD reference manuals from the early-mid 80s do not mention it. It isn't until 4.4BSD that it appears, well after those mentions in SunOS. The sources I have for Solaris ([[Illumos]]) only go back to [[2005]] when [[Solaris|OpenSolaris]] was first made public. # History Basically the `realpath` command was introduced by Sun in their then-named SunOS in the mid 80s. I haven't tried to pull the Illumos sources to see if they have logs going that far back, but I did dig up reference manuals from the 80s to get a general idea. Subsequently, `realpath` was introduced in BSD 4.4 in the mid 90s and then entered the BASE Single UNIX Specification in 1997 - although for reasons I haven't pinned down yet, it seems that 2001 was the date most devs reference - maybe that is when it was ratified. And 2001 is when it made it into FreeBSD. Despite that long history, it didn't make it to the rest of Linux until 2014 and not OpenBSD until 2022! # Features # References ```cardlink url: https://www.maizure.org/projects/decoded-gnu-coreutils/realpath.html title: "Decoded: realpath (coreutils) – MaiZure's Projects" description: "Taking apart the realpath utility (GNU coreutils)" host: www.maizure.org ``` ```cardlink url: https://stackoverflow.com/questions/60802732/are-realpath-portability-concerns-obsolete title: "Are realpath() portability concerns obsolete?" description: "The traditional way to call the Unix realpath() function has been realpath(pathname, buf) where buf is a user-supplied buffer with room for PATH_MAX bytes. This is problematic since PATH_MAX is" host: stackoverflow.com image: https://cdn.sstatic.net/Sites/stackoverflow/Img/[email protected]?v=73d79a89bded ``` ```cardlink url: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/realpath.3.html title: "Mac OS X Manual Page For realpath(3)" description: "HTML versions of the iOS man pages." host: developer.apple.com ``` ```cardlink url: https://www.man7.org/linux/man-pages/man1/realpath.1.html title: "realpath(1) - Linux manual page" host: www.man7.org ``` ```cardlink url: https://www.man7.org/linux/man-pages/man3/realpath.3.html title: "realpath(3) - Linux manual page" host: www.man7.org ``` ## vs Readlink [[realpath - canonicalized absolute pathnames]] vs [[readlink]] # References ```cardlink url: https://unix.stackexchange.com/questions/136494/whats-the-difference-between-realpath-and-readlink-f title: "What's the difference between \"realpath\" and \"readlink -f\"" description: "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 introducedwas fo..." host: unix.stackexchange.com image: https://cdn.sstatic.net/Sites/unix/Img/[email protected]?v=32fb07f7ce26 ``` ```cardlink url: https://stackoverflow.com/questions/59895/how-do-i-get-the-directory-where-a-bash-script-is-located-from-within-the-script title: "How do I get the directory where a Bash script is located from within the script itself?" description: "How do I get the path of the directory in which a Bash script is located, inside that script?I want to use a Bash script as a launcher for another application. I want to change the working directo..." host: stackoverflow.com image: https://cdn.sstatic.net/Sites/stackoverflow/Img/[email protected]?v=73d79a89bded ```