Why are three-argument open calls with auto-updated file descriptors Perl's best practice?

I have two questions about the Perl open function:

1) I seem to remember from Perl Best Practices that the version with three open arguments is better than the two versions of the arguments, for example

 open(OUT, '>>', $file); 

against.

 open(OUT, ">>$file"); 

Why? I tried to tell someone to use a version with three arguments the other day, but it seemed like I could not support anything.

2) I also remember that auto-file descriptors were preferable to descriptor descriptors (they called something else)? And also could not remember why, for example,

 open(my $out, '>>', $file); 

against.

 open(OUT, '>>', $file); 

Is this a strict thing? I seem to remember that I was able to use OUT with strict , but I can’t remember.

+44
scope file-io perl
Sep 25 '09 at 21:51
source share
3 answers
  • Using globs types for file descriptors (such as OUT ) is not a good idea, because they are global for your entire program - you must be sure that no other procedure, including modules in modules, uses the same name (including to the future).
  • Using the bidirectional form open gives your application the wrong behavior caused by variables containing special characters, such as my $f; open $f, ">$some_filename"; my $f; open $f, ">$some_filename"; an error $some_filename where $some_filename containing the leading > changes the behavior of the program.

Using a form with three arguments avoids this by dividing the mode and file name into separate arguments where they cannot intervene.

Moreover, using a lot of arguments form using pipes is a very good idea:

 open $pipe, '|-', 'sendmail', 'fred@somewhere.fake'; 

Better than doing everything as one line - this avoids a possible shell injection, etc.

+62
Sep 25 '09 at 22:02
source share

Scrum # 2:

OUT is a global file descriptor, and using it provides you with insidious errors as follows:

 sub doSomething { my ($input) = @_; # let compare $input to something we read from another file open(F, "<", $anotherFile); @F = <F>; close F; &do_some_comparison($input, @F); } open(F, "<", $myfile); while (<F>) { &doSomething($_); # do'h -- just closed the F filehandle } close F; 
+14
Sep 25 '09 at 21:56
source share

One aspect to keep in mind is that a form with two arguments is broken. Consider a file named "abc" (that is, a file name with a leading space). You cannot open the file:

 open my $foo, ' abc' or die $!; open my $foo, '< abc' or die $!; open my $foo, '< abc' or die $!; # nothing works 

The space is deleted, so the file can no longer be found. Such a scenario is very unlikely, but definitely a problem. The tri-arg form is immune to this:

 open my $foo, '<', ' abc' or die $!; # works 

This perlmonks thread is as good as any issue. Just keep in mind that in 2001 the form with three arguments was still considered new and therefore not suitable for portable code, since Perl programs die with a syntax error if they run on the 5.005 interpreter. This is not so: perl 5.005 is not out of date, it is out of date.

+12
Sep 26 '09 at 17:03
source share



All Articles