What does if( -f ) in Perl do?

后端 未结 5 2131
谎友^
谎友^ 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:26

    See perlfunc.

    It lists all the Perl built-in functions, including the "file test" ones:

    -X FILEHANDLE
    -X EXPR
    -X DIRHANDLE
    -X
    

    Where -X is one of the following:

    -r: File is readable by effective uid/gid.
    -w: File is writable by effective uid/gid.
    -x: File is executable by effective uid/gid.
    -o: File is owned by effective uid.
    
    -R: File is readable by real uid/gid.
    -W: File is writable by real uid/gid.
    -X: File is executable by real uid/gid.
    -O: File is owned by real uid.
    
    -e: File exists.
    -z: File has zero size (is empty).
    -s: File has nonzero size (returns size in bytes).
    
    -f: File is a plain file.
    -d: File is a directory.
    -l: File is a symbolic link.
    -p: File is a named pipe (FIFO), or Filehandle is a pipe.
    -S: File is a socket.
    -b: File is a block special file.
    -c: File is a character special file.
    -t: Filehandle is opened to a tty.
    
    -u: File has setuid bit set.
    -g: File has setgid bit set.
    -k: File has sticky bit set.
    
    -T: File is an ASCII text file (heuristic guess).
    -B: File is a "binary" file (opposite of -T).
    
    -M: Script start time minus file modification time, in days.
    -A: Same for access time.
    -C: Same for inode change time (Unix, may differ for other platforms)
    
    0 讨论(0)
  • 2021-02-05 03:27

    Look for Perl file test operators.

    0 讨论(0)
  • 2021-02-05 03:33

    It tests whether the object specified by <filename> is a plain file (as opposed to binary, or being a directory, etc.).

    0 讨论(0)
  • 2021-02-05 03:38

    if (-f <filename> ) { ... }

    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 <filename> 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 </tmp/.X*/X*>             ) { say "I smell an X11 socket"             }
    
    if (-t STDIN && -t STDOUT        ) { say "smells pretty tty to me"           } 
    
    0 讨论(0)
  • 2021-02-05 03:50

    In Unix, directories can contain the following types of files:

    • Plain (what you would consider a file)
    • Directory
    • Named pipe
    • Named socket
    • ...

    -f tests if the provided name references a file that's a plain file. It will return undef (error ENOENT) if the file doesn't exist, or some other false values if the file exists but it's not plain file (e.g. if it's a directory).

    -X operators

    0 讨论(0)
提交回复
热议问题