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"; ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access