use v5.36;
use autodie; # open/close/etc. die automatically on failure
# Three-argument open with lexical filehandles (always use this form)
open my $in, '<', 'input.txt'; # read
open my $out, '>', 'output.txt'; # write (truncate)
open my $log, '>>', 'app.log'; # append
open my $rw, '+<', 'data.bin'; # read/write
while (my $line = <$in>) { # line by line (memory-efficient)
chomp $line;
next unless length $line;
print {$out} uc($line), "\n"; # braces around the filehandle are good style
}
say {$log} scalar(localtime), ' processed';
close $in; close $out; close $log;
# Without autodie: check every open
open(my $fh, '<', $file) or die "Cannot open '$file': $!";
# Slurp a whole file
my $content = do { local $/; open my $f, '<', 'input.txt'; <$f> };
my @lines = do { open my $f, '<', 'input.txt'; <$f> }; # all lines (list context)
chomp @lines;
use Path::Tiny; # CPAN: the most convenient file API
my $text = path('input.txt')->slurp_utf8;
path('out.txt')->spew_utf8("Hello\n");
my @ls = path('input.txt')->lines_utf8({ chomp => 1 });
path('app.
…
16.2 Encodings and Binary Files
open my $u, '<:encoding(UTF-8)', 'unicode.txt'; # decode UTF-8 on read
open my $w, '>:encoding(UTF-8)', 'out.txt';
open my $bin, '<:raw', 'image.png'; # binary
binmode $bin;
read($bin, my $buffer, 1024); # read 1024 bytes
seek($bin, 0, 0); tell($bin); eof($bin);
16.3 File Tests and Metadata
say 'exists' if -e $file;
say 'plain file' if -f $file;
say 'directory' if -d $path;
say 'readable' if -r $file;
say 'writable' if -w $file;
say 'executable' if -x $file;
say 'size: ', -s $file; # size in bytes (false if zero)
say 'empty' if -z $file;
say 'symlink' if -l $file;
say 'age in days: ', -M $file; # since last modification
my @st = stat($file); # (dev, ino, mode, nlink, uid, gid, rdev, size, atime, mtime, ctime, blksize, blocks)
use File::stat; my $st = stat($file); say $st->size, ' ', scalar localtime $st->mtime;
rename 'old.txt', 'new.txt';
unlink 'temp.txt'; # delete
chmod 0644, 'file.txt';
utime undef, undef, 'file.txt'; # touch
use File::Copy qw(copy move);
copy('a.txt', 'b.txt');
move('b.txt', 'archive/b.txt');
16.4 In-Memory Files, Temp Files and Locking
open my $mem, '<', \$string; # read from a string as if it were a file
open my $buf, '>', \my $captured; # write into a string
use File::Temp qw(tempfile tempdir);
my ($tfh, $tname) = tempfile(UNLINK => 1);
my $tdir = tempdir(CLEANUP => 1);
use Fcntl qw(:flock SEEK_END);
open my $lockfh, '>>', 'shared.log';
flock($lockfh, LOCK_EX) or die "Can't lock: $!"; # exclusive lock
print {$lockfh} "safe write\n";
close $lockfh; # releases the lock