--- name: readlink signature: 'readlink EXPR' signatures: - 'readlink EXPR' - 'readlink' since: 5.0 status: documented categories: ["Filehandles, files, directories"] --- ```{index} single: readlink; Perl built-in ``` *[Filehandles, files, directories](../perlfunc-by-category)* # readlink Return the target path a symbolic link points to. `readlink` asks the kernel what string is stored inside a symbolic link, without following it and without touching the file the link eventually resolves to. The argument is the path of the link itself; the return value is the raw target string as recorded when the link was created. If `EXPR` is omitted, [`$_`](../perlvar) is used. ## Synopsis ```perl readlink EXPR readlink ``` ## What you get back On success, the link target as a string — exactly the bytes stored in the symlink, without any interpretation. On failure, [`undef`](undef), with [`$!`](../perlvar) set to the system error. Typical error codes: - `EINVAL` — the path exists but is not a symbolic link - `ENOENT` — the path does not exist - `EACCES` — a directory component is not searchable - `ELOOP`, `ENAMETOOLONG`, `ENOTDIR` — the usual path-resolution failures on components leading up to the link The returned string is **not** canonicalised and **not** made absolute. A link created with `ln -s ../lib/libfoo.so libfoo.so` returns the literal `"../lib/libfoo.so"`, relative to the directory that contains the link itself — not to the current working directory. Resolving the target to an absolute, real path is the caller's job; see [`Cwd::abs_path`](../../Cwd/abs_path). ## Global state it touches - [`$_`](../perlvar) — read as the default argument when `EXPR` is omitted - [`$!`](../perlvar) — set on failure to the C `errno` from the underlying `readlink(2)` call ## Examples Read a link target directly: ```perl my $target = readlink "/usr/bin/vi"; print defined $target ? "points to $target\n" : "not a symlink: $!\n"; ``` Default argument form inside a loop over filenames: ```perl for (@paths) { next unless -l; # skip anything that isn't a symlink my $t = readlink; # reads $_ print "$_ -> $t\n" if defined $t; } ``` Guard against non-symlinks explicitly. `readlink` on a regular file returns [`undef`](undef) and sets [`$!`](../perlvar) to `EINVAL`: ```perl my $t = readlink $path; if (!defined $t) { die "readlink $path: $!" unless $!{EINVAL}; # not a symlink — handle as a plain file } ``` Resolve a relative link target against the link's own directory, which is the correct base — not the current working directory: ```perl use File::Basename qw(dirname); use File::Spec; my $target = readlink $link // die "readlink $link: $!"; my $resolved = File::Spec->rel2abs($target, dirname($link)); ``` Canonicalise fully (follow every link in the chain, collapse `.` and `..`, produce an absolute path) with [`Cwd::abs_path`](../../Cwd/abs_path): ```perl use Cwd qw(abs_path); my $real = abs_path($link); # undef if any component is missing ``` ## Edge cases - **Not a symlink**: `readlink` on a regular file, directory, or anything else that isn't a symbolic link returns [`undef`](undef) and sets [`$!`](../perlvar) to `EINVAL`. Test with `-l` first if you want to distinguish "not a link" from other errors. - **Missing path**: a component of `EXPR` that doesn't exist gives `ENOENT`, same as any other path-lookup failure. - **Default argument**: bare `readlink` uses [`$_`](../perlvar). No warning is emitted when [`$_`](../perlvar) is [`undef`](undef); the call simply fails with a path-lookup error. - **Trailing components**: `readlink` operates on the final component only — intermediate symlinks in the path are followed normally. `readlink "/a/b/c"` where `/a` is itself a symlink reads the link at `c`, not at `a`. - **Relative target, unchanged**: the returned string is stored verbatim. Never assume the string is absolute, and never join it onto the current working directory — join onto the directory that contains the link, or feed the link path (not the target) to [`Cwd::abs_path`](../../Cwd/abs_path). - **Dangling links**: a link whose target does not exist still reads fine. `readlink` does not stat the target. Use [`lstat`](lstat) to inspect the link itself, [`stat`](stat) to inspect what it points to (and fail if the target is missing). - **Platforms without symlinks**: on systems that do not implement symbolic links, `readlink` raises an exception rather than returning [`undef`](undef). Linux (the only supported pperl target) always has them, so this is relevant only for portable code shared with other targets. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`symlink`](symlink) — create a symbolic link; inverse operation - [`link`](link) — create a hard link (not readable with `readlink`; hard links are indistinguishable from the original name) - [`lstat`](lstat) — `stat` the symlink itself rather than its target; use together with `readlink` to inspect a link fully - `-l` — file test for "is a symbolic link"; check before calling `readlink` to disambiguate `EINVAL` from other errors - [`$!`](../perlvar) — `errno` set on failure; `$!{EINVAL}` distinguishes "not a symlink" from other errors