2011-05-30 137 views
24

我碰到这行代码:Perl中的if(-f <filename>)会做什么?

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

-f出现测试文件名是否存在,但我不知道。谷歌目前没有帮助(谷歌很难“-f”),也没有我的Perl书籍。

任何人都可以请指教?

+0

的'-f'选项是相当怪异。存在的测试是'-e',但'-f'是“普通文件”,它似乎被定义为“不特殊”。它不是二进制的,因为在我的测试中,文件对'-B'和'-f'返回true。 – TLP 2011-05-30 06:46:29

+2

这里学到的教训不是依赖Google的一般结果。 [限于域'perl.org'](http://google.com/search?q=site%3Aperl.org+%2Bf):第二个结果就是你以后的结果。 - 如果他们没有提及'-f',你的书就会吸引很大。更好地得到这些:,并且还有一些堆栈溢出的好建议,搜索标签'[perl]''[books] '。 – daxim 2011-05-30 07:54:47

+0

'-f'只不过是那种熟悉的老式语法糖('statbuf.st_mode&S_IFMT)== S_IFREG'的语法糖。这里的操作问题真的是'',这更有趣。 – tchrist 2011-05-30 18:19:48

回答

30

参见perlfunc

它列出了所有Perl的内置功能,包括 “文件测试” 的:

-X FILEHANDLE 
-X EXPR 
-X DIRHANDLE 
-X 

哪里-X为下列之一:

-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) 
+1

此外,您不必“知道”文档位于perlfunc页面即可获取此文档。你可以通过'perldoc -f -f'找到'-f'的文档 - 就像你可以通过'perldoc -f some_function'找到其他函数的文档一样。 – rohanpm 2011-05-30 22:32:41

+0

纯文件的定义是什么?只是问问。 – 2013-10-09 11:29:59

+0

@JerryLam不是目录,fifo,socket等。 – melpomene 2016-09-11 09:51:58

-3

它测试<filename>指定的对象是否是普通文件(与二进制或作为目录等相对)。

+5

Binary?如果你的意思是非文本的,它们也是纯文件。 '-f'用于区别不同的_types_(如目录,FIFO,套接字等),而不是不同的_content._ – paxdiablo 2011-05-30 06:37:19

+2

(与'-T'比较) – 2011-05-30 06:39:23

+4

它与二进制不是相反的。它与“特殊”相反。 – TLP 2011-05-30 06:48:33

5

在Unix中,目录可以包含以下类型的文件:

  • 平原(你会考虑的文件)
  • 目录
  • 命名管道
  • 名为socket
  • ..

-f测试p rovided名称引用了一个纯文件的文件。如果文件不存在,它将返回undef(错误ENOENT),或者如果文件存在但它不是普通文件(例如,如果它是目录)则返回其他一些假值。

-X operators

2

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

看来,无论是我误解了问题,否则其他人了。

首先,让我们做一些假设。

  1. 让我们假设你有没有超载所有-X前缀元运算符(它要么全部要么都不中),

  2. 让我们还假设你有没有超载<> CIRCUMFIX迭代算子。

假设二者上面给出这两个已知条件的建议立即进行删除保持,则该符号<filename>会做scalar readline(*filename) - 这取决于$/值 - 然后传递结果返回给filetest操作者用于随后的评价,通常但不一定是通过stat(2)。这意味着你最好有一个文件句柄,名字为filename,这样才能工作,除非真正涉及到深度的魔法。

如果还将为<$filename>这样做,除了现在$filename是间接句柄而不是像filename这样的直接句柄。再次,$/受到尊重。使用与它相关的文件句柄正确的文件名实际上是我所做的所有术语。例如:

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

这样的warndie消息居然告诉我,该文件的名称。例如:

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

会告诉我行号的文件的行号和名称。

现在,如果<⋯>的操作数背离允许的无支配的定向对象的规则,即以零或更多美元符号为前缀的空白字符,那么它不是迭代操作符,而是通配符定义符。即使没有通配符也是如此。它只是违反Perl的著名规则Datives,那然后触发备用

这意味着当且仅当filename不与零个或多个前导美元符号合法的裸词 - 如示例/etc/termcap/tmp,*.[Cchy],{,/usr}/bin/c?~/Documents - 然后调用File::Glob::bsd_glob函数指南中那个熟悉的旧同名运算符,而只是在您提供此类函数时,您会期望得到如此有用且常用的函数适当的论据。

这里有很多例子,显示答案排序问题上面引述部分其实就是在问:

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"   } 
+2

我怀疑OP的意思是''作为“文件名占位符”而不是文字代码。即使它们确实代表了这些代码,关于为什么这可能是一个错误的讨论对于OP来说比对''''''可以做的所有事情的论文更有用。 – Schwern 2011-05-30 20:28:27

+0

@Schwern:问题在于我*真的真的*自己写了像'open(FH,<〜tchrist/foofile>)'这样的东西,所以'如果-t​​'在tchrist™代码中是完全正常的。对于一个简单的定理,我更喜欢'open('*ʜᴀɴᴅʟᴇ*,*ᴍᴏᴅᴇ*,*ɴᴀᴍᴇ*')||死的时候我可以逃脱;也就是说,使用*ᴏʙʟɪQᴜᴇsᴍᴀʟʟᴄᴀᴘs*作为metasyntacticisms(“metasyntagmata”?)。但在这里不能这样做。有些人在[uniprops](http://training.perl.com/scripts/uniprops)中使用'''''''''',但对我来说,这几乎看起来像'<ᴡʜᴀᴛᴇᴠᴇʀ>'。 – tchrist 2011-05-30 20:52:01

+0

我相信你确实使用它。而且我也做了一些古怪的事情。事情我会建议大多数其他程序员反对,因为你必须在回答问题时考虑你的观众。观众不像我们。我们是第99百分位,可以将闪电枪的数量提高到10。 – Schwern 2011-05-31 07:32:36