What does if( -f ) in Perl do?

后端 未结 5 2132
谎友^
谎友^ 2021-02-05 03:10

I came across this line of code:

if( -f  ) { ... }

-f appears to test whether the filename exists or not, but I am

5条回答
  •  不思量自难忘°
    2021-02-05 03:38

    if (-f ) { ... }

    It seems that either I have misunderstood the question, or else everybody else has.

    First, let’s make some assumptions.

    1. Let’s assume that you haven’t overloaded all the -X prefix unary operators (it’s either all of them or none of them),

    2. Let’s also assume that you haven’t overloaded the <> circumfix iteration operator.

    Assuming that both of those two givens given above shoul hold, then the notation will do a scalar readline(*filename) — which depends on the value of $/ — and then pass that result back to the filetest operator for subsequent evaluation, usually but not necessarily by way of stat(2). That means that you had best have a filehandle open by the name of filename for this to work, unless truly deep wizardry is involved.

    If will also do this for <$filename>, except now $filename is an indirect handle instead of a direct one like filename. Again, $/ is respected. Using a filename proper for the filehandle associated with it is actually something I do all the term. For example:

    our $fn = "/etc/termcap";
    open($fn, "<", $fn) || die "can't open $fn: $!";
    

    That way the warn and die messages actually tell me the name of the file. For example:

    while (<$fh>) {
         warn "oops" if whatever;
    }
    

    will tell me the line number and the name of the file at which I oopsted.

    Now, if the operand of the <⋯> deviates from the rules for allowed unbraced dative objects, that is, a bareword prefixed by zero or more dollar signs, then it is not the iteration operator but the wildcard burster. This is true even without wildcards. It just has to violate Perl’s famous Rule of Datives, and that then triggers the alternate

    This means that if and only if filename isn’t a legal bareword with zero or more leading dollar signs — such as for example /etc/termcap, /tmp, *.[Cchy], {,/usr}/bin/c?, or ~/Documents — then that familiar old conglobulation operator in the guide of the File::Glob::bsd_glob function is called instead, with exactly the sort of result you would expect of such a useful and commonly used function when supplied with the appropriate argument.

    Here are many examples that show answers to the sort of question the quoted portion above is actually asking:

    use v5.10;  # for the say feature, but not needed for conglobulation
    
    if (-d <~joebob>                 ) { say "joebob has a home"                 }
    if (-d <~joebob/.opera>          ) { say "joebob has an opera directory"     }
    if (-d <~joebob/.ssh>            ) { say "joebob has an ssh directory"       }
    
    if ($n = grep {-e} <~joebob/.*rc>) { say "joebob has $n RC files"            }
    
    if (-f <~joebob/.exrc>           ) { say "joebob has a vi config file"       }
    if (-f <~joebob/.profile>        ) { say "joebob has a sh profile"           }
    if (-f <~joebob/.bashrc>         ) { say "joebob has a bash config script"   }
    if (-f <~joebob/.cshrc>          ) { say "joebob has a csh config script"    }
    if (-f <~joebob/.log{in,out}*>   ) { say "joebob has csh login/out scripts"  }
    
    if (-S              ) { say "I smell an X11 socket"             }
    
    if (-t STDIN && -t STDOUT        ) { say "smells pretty tty to me"           } 
    

提交回复
热议问题