opscape

Files and directories

realpath

Print the absolute, canonical path of a file, with symlinks, . and .. resolved.

realpath [OPTION...] FILE...

9 of 9 examples run in Debian 13.7 on 2026-10-31 · coreutils 9.7-3 · manual: realpath(1)

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
explain
output
/home/dev/demo/notes.txt

The relative name is resolved from the current directory, /home/dev/demo.

Clean up . and ..

realpath ./src/lib/../../data//users.csv
explain
output
/home/dev/demo/data/users.csv

.. steps are applied, . and the double slash disappear.

Paths that do not exist yet

realpath build/output/app
realpath -m build/output/app
output
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
explain
outputexit 1
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
output
../../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/greet
echo "$(dirname "bin/greet")"
echo "$(dirname "$(realpath bin/greet)")"
output
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"
output
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

  • realpath resolves .. after following symlinks, so realpath 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 -z exists 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 realpath since macOS 13 (Ventura), but without GNU options such as -m, -s or --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.

OptionWhat it does
-e, --canonicalize-existingEvery component, including the last, must exist.
-m, --canonicalize-missingNo component needs to exist.
-s, --no-symlinksDo not resolve symlinks; only make the path absolute and tidy.
-L, --logicalResolve .. before symlinks.
-P, --physicalResolve symlinks as they are met (the default).
-q, --quietSuppress most error messages.
--relative-to DIRPrint the result relative to DIR.
--relative-base DIRPrint relative paths only for files under DIR, absolute otherwise.
-z, --zeroEnd each output line with a NUL byte.

Related