Filehandles, files, directories
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, $_ is used.
Synopsis#
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, with
$! set to the system error. Typical error codes:
EINVAL— the path exists but is not a symbolic linkENOENT— the path does not existEACCES— a directory component is not searchableELOOP,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.
Global state it touches#
Examples#
Read a link target directly:
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:
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 and sets $! to EINVAL:
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:
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:
use Cwd qw(abs_path);
my $real = abs_path($link); # undef if any component is missing
Edge cases#
Not a symlink:
readlinkon a regular file, directory, or anything else that isn’t a symbolic link returnsundefand sets$!toEINVAL. Test with-lfirst if you want to distinguish “not a link” from other errors.Missing path: a component of
EXPRthat doesn’t exist givesENOENT, same as any other path-lookup failure.Default argument: bare
readlinkuses$_. No warning is emitted when$_isundef; the call simply fails with a path-lookup error.Trailing components:
readlinkoperates on the final component only — intermediate symlinks in the path are followed normally.readlink "/a/b/c"where/ais itself a symlink reads the link atc, not ata.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.Dangling links: a link whose target does not exist still reads fine.
readlinkdoes not stat the target. Uselstatto inspect the link itself,statto inspect what it points to (and fail if the target is missing).Platforms without symlinks: on systems that do not implement symbolic links,
readlinkraises an exception rather than returningundef. 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— create a symbolic link; inverse operationlink— create a hard link (not readable withreadlink; hard links are indistinguishable from the original name)lstat—statthe symlink itself rather than its target; use together withreadlinkto inspect a link fully-l— file test for “is a symbolic link”; check before callingreadlinkto disambiguateEINVALfrom other errors$!—errnoset on failure;$!{EINVAL}distinguishes “not a symlink” from other errors