Opening Files with Unusual Filenames
Problem
You want to open a file with a funny filename, like
"-"
or one that starts with <, >, or
|
, has leading or trailing whitespace; or ends
with |
. You don’t want these to trigger
open
’s do-what-I-mean behavior, since in
this case, that’s not what you mean.
Solution
Use open
like this:
$filename =~ s#^(\s)#./$1#; open(HANDLE, "< $filename\0") or die "cannot open $filename : $!\n";
Or simply use sysopen
:
sysopen(HANDLE, $filename, O_RDONLY) or die "cannot open $filename: $!\n";
Discussion
The open
function uses a single string to
determine both the filename and the mode—the way the file is
to be opened. If your filename begins with the characters used to
indicate the mode, open
can easily do something
unexpected. Imagine the following code:
$filename = shift @ARGV; open(INPUT, $filename) or die "Couldn't open $filename : $!\n";
If the user gave ">/etc/passwd"
as the filename
on the command line, this code would attempt to open
/etc/passwd for writing—definitely
unsafe! We can try to give an explicit mode, say for writing:
open(OUTPUT, ">$filename") or die "Couldn't open $filename for writing: $!\n";
but even this would let the user give a filename of
"
>data"
and the code would
append to the file data
instead of erasing the old
contents.
The easiest solution is sysopen
, which takes the
mode and filename as separate arguments:
use Fcntl; # for file constants sysopen(OUTPUT, $filename, O_WRONLY|O_TRUNC) or die "Can't open $filename for writing: $!\n"; ...
Get Perl Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.