Linux readlink Command: Inspect Symbolic Link Targets

readlink is a command that outputs the target path stored in a symbolic link file. It is useful for checking whether the link contains a relative path or where a broken link points.

GNU readlink also supports path normalization with -f, -e, and -m, but GNU Coreutils recommends using realpath, which has clearer functions and naming, for general path normalization.

What is the readlink command?

When you specify a symbolic link as an argument, it outputs the target string stored in the link.

readlink current

If the current link points to releases/2026-09, it will output as follows.

releases/2026-09

This value may be a relative path interpreted based on the location of the link. The default readlink shows it close to the stored form without converting the target string to an absolute path.

Basic Syntax and Usage

readlink [options] file...

You can first create an example link with ln -s and then check it.

ln -s releases/2026-09 current
readlink current

If you specify a regular file or directory without any options, there is no link target value, so nothing is output, and it fails with a non-zero exit status.

readlink /etc/passwd
printf '%s\n' "$?"

Understanding Relative and Absolute Links

Link Storing a Relative Path

The target of a relative link is interpreted based on the directory where the link is placed, not the current terminal location.

ln -s ../shared/config.yml /srv/app/config.yml
readlink /srv/app/config.yml

The output is ../shared/config.yml. This path is resolved relative to /srv/app and points to /srv/shared/config.yml.

Link Storing an Absolute Path

ln -s /srv/releases/2026-09 /srv/current
readlink /srv/current

An absolute link outputs the target string starting from the root, like this.

/srv/releases/2026-09

Absolute links have a clear location, but they can easily break if the file tree is moved to a different path. Choose relative or absolute links considering your deployment structure and portability.

Checking Broken Symbolic Links

Even if the target file does not exist, the basic readlink can read the stored target string as long as the symbolic link itself remains.

ln -s missing-target broken-link
readlink broken-link
missing-target

The existence of the link target can be checked separately as follows.

if [ -L broken-link ] && [! -e broken-link ]; then
 printf '%s\n' 'This is a broken symbolic link.'
fi

-L checks the existence of the link itself, while -e checks the existence of the target it points to. Permission issues or link cycles may also affect the result.

Path normalization options

GNU readlink also provides a mode to normalize paths in addition to outputting the link target string.

Option Action
-f, --canonicalize All path components except the last must exist, and symbolic links and dot components are resolved.
-e, --canonicalize-existing All components including the last item must exist.
-m, --canonicalize-missing Nonexistent components are also assumed to be directories to normalize the path.

Print a canonical path with -f

readlink -f /srv/current/config.yml

Outputs the absolute path with symbolic links and ., .. resolved. The last component may be missing, but the preceding components must exist.

Require every component to exist with -e

readlink -e /srv/current/config.yml

The entire path, including the target file, must exist for the result to be output. It does not prevent a race condition where the target changes between existence check and actual use.

Allow missing components with -m

readlink -m /srv/future/../uploads/new-file.txt

Handles intermediate components that do not exist, so it can be used for path planning or string arrangement. There is no guarantee that the output location can actually be created.

Handling multiple links and output separation

Check multiple symbolic links

GNU readlink can handle multiple links at once.

readlink current previous config-link

Each target string is output line by line. If the correspondence between input and output is important, it is clearer to display the link name along with the result in a loop.

for link in current previous config-link; do
  target=$(readlink -- "$link") || continue
  printf '%s -> %s\n' "$link" "$target"
done

The difference between -n and -z

-n or --no-newline omits the trailing separator character when processing a single link. Using it with multiple files may generate warnings.

readlink -n current

-z or --zero outputs a NUL character instead of a newline at the end of each result. In automation where filenames and link targets may contain newlines, -z is clearer.

readlink -z current previous

Comparison of readlink, realpath, ls, and stat

Command Main Purpose Features
readlink Check the target string stored in a link Even broken links can be read as the link itself
realpath Filename normalization and relative path calculation GNU is primarily recommended for path normalization
ls -l Check links and targets in the list in a way that's easy for humans to read Displayed together with other list information, making it unsuitable for parsing
stat Check detailed metadata of the link or target You can check inode, permissions, time, and file type

If only the target string of the link is needed in automation, readlink is appropriate. If the purpose is general path normalization and relative path conversion, realpath is clearer.

Using in shell scripts

Check whether the link target is a relative path

target=$(readlink -- "$link") || {
 printf '%s\n' 'Cannot read the symbolic link.' >&2
 exit 1
}

case "$target" in
 /*) printf '%s\n' 'This is an absolute path link.';;
 *) printf '%s\n' 'This is a relative path link.';;
esac

To calculate a relative path to its actual location, it should be based on the directory containing the link. Simply appending it to the current working directory can lead to an incorrect path.

Check the exit status

Check whether the command succeeded rather than only checking if the output is empty. While the link target cannot be an empty string, this expresses the intention of error handling more clearly.

if target=$(readlink -- "$link"); then
 printf '%s\n' "$target"
else
 printf 'Failed to read the link: %s\n' "$link" >&2
fi

Summary of major options

Option Description
-f, --canonicalize Normalize the path whose components exist except for the last item.
-e, --canonicalize-existing All path components must exist for success.
-m, --canonicalize-missing Treat non-existent components as directories.
-n, --no-newline Omit the output delimiter after a single result.
-z, --zero Terminate each result with a NUL character.
-q, -s, --quiet Suppresses most error messages.
-v, --verbose Displays error messages.

Common issues

Fails without any output.

In default mode, the specified path may not be a symbolic link or the link itself may be inaccessible. Check the exit status and, if necessary, display error messages with -v.

The relative link target appears to be incorrect.

The output relative path should be interpreted based on the directory containing the link. It is not based on the current directory from which the command is executed.

readlink -f does not work on other systems.

Normalization options, including -f, have implementation differences. In scripts that require portability, check whether the target operating system supports it, and if your goal is path normalization, also compare available realpath implementations and options.

FAQ

Does readlink read the content of the file that a symbolic link points to?

No. In its default mode, it outputs the target path string stored in the link file. It does not read the content of the target file.

Can broken symbolic links also be checked with readlink?

If the link itself exists and can be read, you can check the stored target string with the default readlink. The -e normalization only succeeds if the actual target exists.

Relative paths are output. How can I check the absolute path?

In a GNU environment, you can use readlink -f link, but for general path normalization, using realpath is clearer in terms of functionality and intent.

Why use readlink instead of ls -l?

ls -l is suitable for human-readable listings, while readlink only outputs the target string, making it convenient for scripts. In automation, be sure to also handle exit status and filename separation.

Related articles and official documentation

More in This Category
Linux uniq Command: Remove or Count Adjacent Duplicate Lines

Linux uniq Command: Remove or Count Adjacent Duplicate Lines

Learn how to remove or count adjacent duplicate lines with the Linux uniq command, including practical examples, key options, and important precautions.

Linux gzip Command: Compress a File in gzip Format

Linux gzip Command: Compress a File in gzip Format

Learn how to compress a File in gzip Format with the Linux gzip command, including practical examples, key options, and important precautions.

Linux Tutorial / Understand Users, Groups, and File Ownership

Linux Tutorial / Understand Users, Groups, and File Ownership

Understand UIDs, GIDs, primary and supplementary groups, and file ownership, then inspect them safely with id, groups, getent, ls, and stat.

Linux tree Command: Display a Directory Tree

Linux tree Command: Display a Directory Tree

Learn how to use the Linux tree command to display directory contents as a readable hierarchy and control depth and filtering, with essential options, practical examples, output interpretation, and common troubleshooting tips.

Linux reboot Command: Restart the System Safely

Linux reboot Command: Restart the System Safely

Learn how to restart the System Safely with the Linux reboot command, including practical examples, key options, and important precautions.

Linux Tutorial / Choosing a Linux Distribution

Linux Tutorial / Choosing a Linux Distribution

Explore major Linux distributions and learn when to choose Ubuntu LTS or Rocky Linux for study and server practice. Compare package management, release policies, and practical selection criteria.

Linux host Command: Look Up DNS Names and Addresses

Linux host Command: Look Up DNS Names and Addresses

Learn how to look Up DNS Names and Addresses with the Linux host command, including practical examples, key options, and important precautions.

Linux mkfs Command: Create a New Filesystem

Linux mkfs Command: Create a New Filesystem

Learn how to create a New Filesystem with the Linux mkfs command, including practical examples, key options, and important precautions.

Linux mount Command: Inspect and Mount Filesystems

Linux mount Command: Inspect and Mount Filesystems

Learn how to inspect and Mount Filesystems with the Linux mount command, including practical examples, key options, and important precautions.

Linux tee Command: Display and Save Pipeline Output

Linux tee Command: Display and Save Pipeline Output

Learn how to display and Save Pipeline Output with the Linux tee command, including practical examples, key options, and important precautions.