Files and directories
readlink
Print where a symbolic link points, or with -f the fully resolved path of any file.
readlink [OPTION...] FILE...
Without options, readlink prints the contents of a symbolic link: the target text exactly as
it was stored by ln -s, which may be relative and may not even exist. If the file is not a
symlink, it prints nothing and fails.
With -f, -e or -m it canonicalizes instead: follows every link in every component and
prints an absolute path, the same job as realpath. readlink -f is the older, more widely
known spelling, so you will see it in many scripts.
Examples
Where does a symlink point
readlink link-to-notes
notes.txt
The stored target is printed as-is: notes.txt, relative to the link's directory.
A regular file is not a link
readlink notes.txt
(no output)
For anything but a symlink, plain readlink prints nothing and exits with 1. That makes it a
quiet "is this a symlink" test, though [ -L file ] is clearer.
One level versus fully resolved
Setup run before this example
ln -s link-to-notes second-linkreadlink second-link
readlink -f second-link
link-to-notes /home/dev/demo/notes.txt
second-link points to link-to-notes, which points to notes.txt. Plain readlink shows
one hop; -f follows the whole chain and prints an absolute path.
Canonical path of any file
readlink -f src/../data/./users.csv
/home/dev/demo/data/users.csv
-f works on regular files too: .. and . are resolved and the result is absolute.
Broken links
Setup run before this example
ln -s old-config.json config.jsonreadlink config.json
readlink -f config.json
readlink -e config.json
old-config.json /home/dev/demo/old-config.json
Plain readlink still shows the target text. -f prints the path the target would have,
since only the last component may be missing. -e requires the target to exist, prints
nothing and fails.
Find what a process has open
readlink /proc/$$/exe
readlink /proc/$$/cwd
/usr/bin/bash /home/dev/demo
On Linux, /proc/PID/exe and /proc/PID/cwd are symlinks to the program a process is
running and its working directory. $$ is this shell's process ID.
Find the real program behind a command
readlink -f "$(command -v awk)"
/usr/bin/gawk
/usr/bin/awk is a symlink through the Debian alternatives system. readlink -f follows the
chain to the program that actually runs, gawk.
Common pitfalls
readlink fileon a non-link prints nothing; a script that uses$(readlink "$f")as a path will get an empty string. Usereadlink -forrealpathwhen you want a path either way.The target text from plain
readlinkis relative to the link's directory, not to your current directory.
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).
readlink -fworks on GNU and on macOS 12.3 and later; older macOS lacks it.-eand-mare GNU-only.
Options worth knowing
A selection, described in our own words. For the full list, see readlink(1) or readlink --help.
| Option | What it does |
|---|---|
-f, --canonicalize | Resolve all links; every component but the last must exist. |
-e, --canonicalize-existing | Resolve all links; every component must exist. |
-m, --canonicalize-missing | Resolve all links; no component needs to exist. |
-n, --no-newline | Do not print the trailing newline. |
-q, --quiet | Suppress most error messages. |
-s, --silent | Same as -q. |
-v, --verbose | Report errors. |
-z, --zero | End each output line with a NUL byte. |
Related
realpathPrint the absolute, canonical path of a file, with symlinks, . and .. resolved.lnMake links between files, symbolic (-s) or hard.statShow a file's metadata (size, permissions, owner, inode, timestamps), or print chosen fields in your own format.dirnameStrip the last component from a path, leaving the directory part.