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 uptime Command: Check Uptime and Load Averages

Linux uptime Command: Check Uptime and Load Averages

Learn how to use the Linux uptime command to check how long the system has been running and interpret load averages, with essential options, practical examples, output interpretation, and common troubleshooting tips.

Linux help Command: Read Help for Bash Built-in Commands

Linux help Command: Read Help for Bash Built-in Commands

Learn how to use the Linux help command to read usage information for Bash built-in commands, with essential options, practical examples, output interpretation, and common troubleshooting tips.

Linux chgrp Command: Change a File's Group

Linux chgrp Command: Change a File's Group

Learn how to change a File's Group with the Linux chgrp command, including practical examples, key options, and important precautions.

Linux rsync Command: Synchronize Files and Directories

Linux rsync Command: Synchronize Files and Directories

Learn how to synchronize Files and Directories with the Linux rsync command, including practical examples, key options, and important precautions.

Linux pgrep Command: Find Process IDs by Name or Criteria

Linux pgrep Command: Find Process IDs by Name or Criteria

Learn how to find Process IDs by Name or Criteria with the Linux pgrep command, including practical examples, key options, and important precautions.

Linux ss Command: Inspect Open Ports and Sockets

Linux ss Command: Inspect Open Ports and Sockets

Learn how to inspect Open Ports and Sockets with the Linux ss command, including practical examples, key options, and important precautions.

Linux file Command: Identify File Types and Formats

Linux file Command: Identify File Types and Formats

Learn how to use the Linux file command to identify file formats from their contents instead of filename extensions, with essential options, practical examples, output interpretation, and common troubleshooting tips.

Linux traceroute Command: Trace Routers on the Way to a Host

Linux traceroute Command: Trace Routers on the Way to a Host

Learn how to trace Routers on the Way to a Host with the Linux traceroute command, including practical examples, key options, and important precautions.

Linux nslookup Command: Query DNS Names and Records

Linux nslookup Command: Query DNS Names and Records

Learn how to query DNS Names and Records with the Linux nslookup command, including practical examples, key options, and important precautions.

Linux info Command: Browse GNU Documentation

Linux info Command: Browse GNU Documentation

Learn how to use the Linux info command to browse hierarchical GNU manuals and navigate Info nodes, with essential options, practical examples, output interpretation, and common troubleshooting tips.