Files and directories
realpath
Print the absolute, canonical path of a file, with symlinks, . and .. resolved.
realpath [OPTION...] FILE...
realpath turns any path into an absolute one with no ., no .., no repeated slashes and no
symbolic links. It answers "where exactly is this file?", which is what scripts need before
comparing two paths, storing a path in a config file, or finding their own location.
By default every component except the last must exist. -m drops that requirement and works
on pure strings; -e requires that all of it exists. -s keeps symlinks unresolved, and
--relative-to computes a relative path between two places, something no other standard tool
does as easily.
readlink -f overlaps heavily with realpath; on GNU systems they share code.
Examples
Absolute path of a file
realpath notes.txt
/home/dev/demo/notes.txt
The relative name is resolved from the current directory, /home/dev/demo.
Resolve a symbolic link
realpath link-to-notes
/home/dev/demo/notes.txt
The link is followed, so the result names the real file, notes.txt.
Clean up . and ..
realpath ./src/lib/../../data//users.csv
/home/dev/demo/data/users.csv
.. steps are applied, . and the double slash disappear.
Keep symlinks as they are
realpath -s link-to-notes src/../link-to-notes
/home/dev/demo/link-to-notes /home/dev/demo/link-to-notes
-s (--no-symlinks) makes the path absolute and removes .. textually, but leaves the
link itself unresolved.
Paths that do not exist yet
realpath build/output/app
realpath -m build/output/app
realpath: build/output/app: No such file or directory /home/dev/demo/build/output/app
By default only the last component may be missing. build/ does not exist either, so the
first call prints an error (and would exit with 1). -m resolves the path as a string and
succeeds, which is what you want for a file you are about to create.
Require that the file exists
realpath -e notes.md
realpath: notes.md: No such file or directory
-e makes even a missing last component an error, which turns realpath into an existence
check that also gives you the canonical name.
Compute a relative path between two places
realpath --relative-to=src/lib data/users.csv
realpath --relative-to=. /home/dev/demo/logs/app.log
../../data/users.csv logs/app.log
--relative-to=DIR prints the path as seen from DIR, which is exactly what you need when
writing a relative symlink or an include path.
A script's real directory, even through a symlink
Setup run before this example
mkdir -p bin
ln -s ../scripts/greet.sh bin/greetecho "$(dirname "bin/greet")"
echo "$(dirname "$(realpath bin/greet)")"
bin /home/dev/demo/scripts
dirname alone reports where the link is; realpath first resolves the link, so the
second line is where the script really lives.
Check whether two paths are the same file
a=$(realpath link-to-notes)
b=$(realpath ./src/../notes.txt)
[ "$a" = "$b" ] && echo "same file: $a"
same file: /home/dev/demo/notes.txt
Canonical paths can be compared as strings. (For hard links, compare inode numbers with
stat instead.)
Common pitfalls
realpathresolves..after following symlinks, sorealpath link/..is the parent of the link's target. Use-s(or-L) if you mean the logical parent.Command substitution strips trailing newlines, so a file name that ends in a newline cannot survive
$(realpath ...); such names are rare but-zexists for that case.
GNU vs BSD and macOS
The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).
macOS has a
realpathsince macOS 13 (Ventura), but without GNU options such as-m,-sor--relative-to; older macOS has none. Install coreutils (grealpath) for the GNU version.
Options worth knowing
A selection, described in our own words. For the full list, see realpath(1) or realpath --help.
| Option | What it does |
|---|---|
-e, --canonicalize-existing | Every component, including the last, must exist. |
-m, --canonicalize-missing | No component needs to exist. |
-s, --no-symlinks | Do not resolve symlinks; only make the path absolute and tidy. |
-L, --logical | Resolve .. before symlinks. |
-P, --physical | Resolve symlinks as they are met (the default). |
-q, --quiet | Suppress most error messages. |
--relative-to DIR | Print the result relative to DIR. |
--relative-base DIR | Print relative paths only for files under DIR, absolute otherwise. |
-z, --zero | End each output line with a NUL byte. |
Related
readlinkPrint where a symbolic link points, or with -f the fully resolved path of any file.dirnameStrip the last component from a path, leaving the directory part.basenameStrip the directory part (and optionally a suffix) from a path, leaving the file name.pwdPrint the full path of the current working directory.lnMake links between files, symbolic (-s) or hard.