3.2.102 openopen
This function opens the file whose filename is given by
After the filehandle is determined, the filename string is processed. First,
any leading and trailing whitespace is removed from the string.
Then the string is examined on both ends for characters specifying how
the file is to be opened. (By an amazing coincidence, these characters
look just like the characters you'd use to indicate I/O redirection to the
Bourne shell.) If the filename begins with
Any pipe command containing shell metacharacters is passed to
/bin/sh
for execution; otherwise it is executed directly by
Perl. The filename "
If you're unfortunate enough to be running Perl on a system that
distinguishes between text files and binary files (modern operating
systems don't care), then you should check out
binmode
for tips
for dealing with this. The key distinction between systems that need
binmode
and those that don't is their text file formats.
Systems like UNIX and Plan9 that delimit lines with a single
character, and that encode that character in C as Here is some code that shows the relatedness of a filehandle and a variable of the same name: $ARTICLE = "/usr/spool/news/comp/lang/perl/misc/38245"; open ARTICLE or die "Can't find article $ARTICLE: $!\n"; while (<ARTICLE>) {... Append to a file like this: open LOG, '>>/usr/spool/news/twitlog'; # (`log' is reserved) Pipe your data from a process: open ARTICLE, "caesar <$article |"; # decrypt article with rot13
Here Or pipe your data to a process: open EXTRACT, "|sort >/tmp/Tmp$$"; # $$ is our process number
In this next example we show one way to do recursive opens, via
indirect filehandles. The files will be opened on filehandles
# Process argument list of files along with any includes. foreach $file (@ARGV) { process($file, 'fh00'); } sub process { local($filename, $input) = @_; $input++; # this is a string increment unless (open $input, $filename) { print STDERR "Can't open $filename: $!\n"; return; } while (<$input>) { # note the use of indirection if (/^#include "(.*)"/) { process($1, $input); next; } ... # whatever } close $input; }
You may also, in the Bourne shell tradition, specify an
#!/usr/bin/perl open SAVEOUT, ">&STDOUT"; open SAVEERR, ">&STDERR"; open STDOUT, ">foo.out" or die "Can't redirect stdout"; open STDERR, ">&STDOUT" or die "Can't dup stdout"; select STDERR; $| = 1; # make unbuffered select STDOUT; $| = 1; # make unbuffered print STDOUT "stdout 1\n"; # this propagates to print STDERR "stderr 1\n"; # subprocesses too close STDOUT; close STDERR; open STDOUT, ">&SAVEOUT"; open STDERR, ">&SAVEERR"; print STDOUT "stdout 2\n"; print STDERR "stderr 2\n";
If you specify
open
If you open a
pipe to or from the command " open FOO, "|tr '[a-z]' '[A-Z]'"; open FOO, "|-" or exec 'tr', '[a-z]', '[A-Z]'; open FOO, "cat -n file|"; open FOO, "-|" or exec 'cat', '-n', 'file'; Explicitly closing any piped filehandle causes the parent process to wait for the child to finish, and returns the status value in $? . On any operation which may do a fork, unflushed buffers remain unflushed in both processes, which means you may need to set $| on one or more filehandles to avoid duplicate output (and then do output to flush them).
Filehandles Using the constructor from the FileHandle module, described in Chapter 7 , you can generate anonymous filehandles which have the scope of whatever variables hold references to them, and automatically close whenever and however you leave that scope: use FileHandle; ... sub read_myfile_munged { my $ALL = shift; my $handle = new FileHandle; open $handle, "myfile" or die "myfile: $!"; $first = <$handle> or return (); # Automatically closed here. mung $first or die "mung failed"; # Or here. return $first, <$handle> if $ALL; # Or here. $first; # Or here. } In order to open a file with arbitrary weird characters in it, it's necessary to protect any leading and trailing whitespace, like this: $file =~ s#^(\s)#./$1#; open (FOO, "< $file\0"); But we've never actually seen anyone use that in a script... If you want a real C open (2), then you should use the sysopen function. This is another way to protect your filenames from interpretation. For example: use FileHandle; sysopen HANDLE, $path, O_RDWR|O_CREAT|O_EXCL, 0700 or die "sysopen $path: $!"; HANDLE->autoflush(1); HANDLE->print("stuff $$\n"); seek HANDLE, 0, 0; print "File contains: ", <HANDLE>; See seek for some details about mixing reading and writing. |
|