open my $fh, '<', $filename
or die "Could not open $filename for reading: $!";
my $contents = do { local $/; <$fh> };
After opening the file (read man perlio
if you want to read specific file encodings instead of raw bytes), the trick is in the do
block: <$fh>
, the file handle in a diamond operator, returns a single record from the file. The "input record separator" variable $/
specifies what a "record" is—by default it is set to a newline character so "a record" means "a single line". As $/
is a global variable, local
does two things: it creates a temporary local copy of $/
that will vanish at the end of the block, and gives it the (non-)value undef
(the "value" which Perl gives to uninitialized variables). When the input record separator has that (non-)value, the diamond operator will return the entire file. (It considers the entire file to be a single line.)
Using do
, you can even get around manually opening a file. For repeated reading of files,
sub readfile { do { local(@ARGV,$/) = $_[0]; <> } }
my $content = readfile($filename);
can be used. Here, another global variable(@ARGV
) is localized to simulate the same process used when starting a perl script with parameters. $/
is still undef
, since the array in front of it "eats" all incoming arguments. Next, the diamond operator <>
again delivers one record defined by $/
(the whole file) and returns from the do
block, which in turn return from the sub.
The sub has no explicit error handling, which is bad practice! If an error occurs while reading the file, you will receive undef
as return value, as opposed to an empty string from an empty file.
Another disadvantage of the last code is the fact that you cannot use PerlIO for different file encodings—you always get raw bytes.