logo
Free, unlimited AI code reviews that run on commit
git-lrc git-lrc GitHub Install Now We'd appreciate a star git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt

Perl::Critic::Policy::ValuesAndExpressions::ProhibitFiletest_f - don't use the -f file test

Description

       This policy is part of the "Perl::Critic::Pulp" add-on.  It asks you not to use the "-f" file test
       because doing so is usually wrong or unnecessarily restrictive.  On that basis this policy is under the
       "bugs" theme and medium severity, see "POLICY THEMES" in Perl::Critic.

       "-f" is not the opposite of "-d"
           If you're traversing a tree and want to distinguish files from directories to descend into, then "-d"
           should be used so device files or named pipes can be processed.

               if (-f $filename) {      # bad
                 process ($filename);
               } else {
                 descend ($filename);
               }

               if (-d $filename) {      # better
                 descend ($filename);
               } else {
                 process ($filename);
               }

       "-f" doesn't mean readable/writable/seekable
           Char  specials  and  named  pipes  are  perfectly good for reading and writing, and char specials can
           support seeking.  Demanding "-f" is an unnecessary restriction.  You might  only  ever  use  ordinary
           files  normally,  but  there's no need to prevent someone else running it on a tape drive, /dev/null,
           etc.  You always have to test each "seek()" etc for success anyway, and that will tell you if a  file
           is seekable.

               seek HANDLE, 123, 0
                 or die "Cannot seek: $!";

       "-e" is better than "-f"
           A  few  inflexible functions or operations may not have good "file not found" behaviour and may force
           you to check for a file before invoking.  Using "-e" is better than "-f" since as described above  it
           doesn't unnecessarily disallow device files.

               if (-f $filename) {      # bad
                 require $filename;
               }

               if (-e $filename) {      # better
                 require $filename;
               }

       "-f" before opening is a race condition
           Testing  a  filename  before opening is bad.  Any test before opening is useless because the file can
           change or be removed in between the  test  and  the  open  ("-X"  in  perlfunc,  and  "Consider  this
           carefully" in filetest, note this about "-r" etc too).

               if (-f $filename) {               # bad
                 open HANDLE, '<', $filename
               }

           If  you  want  to  know if the file can be opened then open the file!  The error return from "open()"
           must be checked, so a test beforehand only duplicates that, and is an opportunity to wrongly  presume
           what the system or the user's permissions can or can't do.

           When opening, "ENOENT" will say if there was no such file, or "EISDIR" if it's in fact a directory.

               if (! open HANDLE, '<', $filename) {  # better
                 if ($! == POSIX::ENOENT()) {
                   ...
                 }
               }

           If you really do want to enquire into the nature of the file, in order to only accept ordinary files,
           then  open  first  and  "-f"  on  the  handle.   But that's unusual except for an archiving or backup
           program.

           Incidentally, the error message in $! is normally the best  thing  to  print.   It  can  be  slightly
           technical,  but  its wording will at least be familiar from other programs and is translated into the
           user's locale language.

   Disabling
       Most uses of "-f" tend to shell script style code written in  Perl.   In  the  shell,  it's  usually  not
       possible  to  do  better  than such tests (though "-d" or "-e" are still generally better than "-f"), but
       Perl can do the right thing.

       A blanket prohibition like this policy is harsh, but is meant as a building block or at least to make you
       think carefully whether "-f" is really right.  As always you can disable "ProhibitFiletest_f"  from  your
       .perlcriticrc in the usual way (see "CONFIGURATION" in Perl::Critic),

           [-ValuesAndExpressions::ProhibitFiletest_f]

Home Page

Name

       Perl::Critic::Policy::ValuesAndExpressions::ProhibitFiletest_f - don't use the -f file test

See Also

       Perl::Critic::Pulp, Perl::Critic, "open" in perlfunc, "ERRNO" in POSIX, Errno, errno(3)

See Also