2011-05-30 22 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