檔案測試,其中 X 是下列字母之一。此單元運算子接受一個參數,可能是檔案名稱、檔案處理常式或目錄處理常式,並測試相關檔案以查看是否為真。如果省略參數,則測試 $_
,但 -t
例外,它測試 STDIN。除非另有說明,否則它會傳回 1
表示為真,傳回 ''
表示為假。如果檔案不存在或無法檢查,它會傳回 undef
並設定 $!
(errno)。除了 -l
測試之外,它們都會追蹤符號連結,因為它們使用 stat()
而不是 lstat()
(因此無法檢查懸空符號連結,因此會報告失敗)。
儘管名稱很奇怪,但優先順序與任何其他命名單元運算子相同。運算子可以是
-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 (false if symlinks aren't
supported by the file system).
-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 or UTF-8 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)
範例
while (<>) {
chomp;
next unless -f $_; # ignore specials
#...
}
請注意,-s/a/b/
並不會執行否定取代。不過,-exp($foo)
仍會如預期般運作:只有連接在減號後面的單一字母會被解釋為檔案測試。
這些運算子不會受到上述「看起來像函式規則」的影響。也就是說,運算子後面的開括號不會影響後續程式碼中多少部分構成參數。請在運算子前面加上開括號,以將其與後面的程式碼分開(當然,這僅適用於優先順序高於單元運算子的運算子)
-s($file) + 1024 # probably wrong; same as -s($file + 1024)
(-s $file) + 1024 # correct
檔案權限運算子 -r
、-R
、-w
、-W
、-x
和 -X
的預設解釋僅根據檔案模式以及使用者的 uid 和 gid。可能還有其他原因導致你無法實際讀取、寫入或執行檔案:例如網路檔案系統存取控制、ACL(存取控制清單)、唯讀檔案系統和無法辨識的可執行格式。請注意,使用這六個特定運算子來驗證是否可以執行某些操作通常是錯誤的,因為它可能會導致競爭條件。
另外請注意,對於本機檔案系統上的超級使用者,-r
、-R
、-w
和 -W
測試總是會傳回 1,而如果模式中設定任何執行位元,-x
和 -X
則會傳回 1。因此,由超級使用者執行的指令碼可能需要執行 stat
來判斷檔案的實際模式,或暫時將其有效 uid 設定為其他值。
如果你正在使用 ACL,則有一個名為 filetest
的實用程式,它可能會產生比單純的 stat
模式位元更準確的結果。在 use filetest 'access'
下,上述檔案測試會測試是否可以使用 access(2) 系列系統呼叫授予(或不授予)權限。另外請注意,在這個實用程式下,-x
和 -X
測試可能會傳回 true,即使沒有設定任何執行權限位元(或任何額外的執行權限 ACL)。這種奇怪的現象是基於底層系統呼叫的定義。另外請注意,由於 use filetest 'access'
的實作,當這個實用程式生效時,_
特殊檔案句柄不會快取檔案測試的結果。請閱讀 filetest
實用程式的文件,以取得更多資訊。
-T
和 -B
測試以下列方式運作。檔案的第一個區塊或類似區塊會被檢查,以查看它是否為包含非 ASCII 字元的有效 UTF-8。如果是,它就是 -T
檔案。否則,檔案的相同部分會被檢查是否有奇怪的字元,例如奇怪的控制碼或設定最高位元組的字元。如果超過三分之一的字元很奇怪,它就是 -B
檔案;否則,它就是 -T
檔案。此外,任何在檢查部分中包含零位元組的檔案都被視為二進位檔案。(如果在包含 LC_CTYPE
的 use locale 範圍內執行,奇怪的字元就是任何在目前區域設定中無法列印或不是空白的字元。)如果在檔案處理上使用 -T
或 -B
,會檢查目前的 IO 緩衝區,而不是第一個區塊。-T
和 -B
都會在空檔案或測試檔案處理時檔案在 EOF 時傳回 true。由於您必須讀取檔案才能執行 -T
測試,因此在大部分情況下,您會想要先對檔案使用 -f
,例如 next unless -f $file && -T $file
。
如果任何檔案測試(或 stat
或 lstat
算子)給予由單一底線組成的特殊檔案處理,則會使用前一個檔案測試(或 stat
算子)的 stat 結構,以儲存系統呼叫。(這不適用於 -t
,而且您需要記住 lstat
和 -l
會在 stat 結構中保留符號連結的值,而不是真實檔案。)(此外,如果 stat 緩衝區是由 lstat
呼叫填寫的,-T
和 -B
會使用 stat _
的結果重設它)。範例
print "Can do.\n" if -r $a || -w _ || -x _;
stat($filename);
print "Readable\n" if -r _;
print "Writable\n" if -w _;
print "Executable\n" if -x _;
print "Setuid\n" if -u _;
print "Setgid\n" if -g _;
print "Sticky\n" if -k _;
print "Text\n" if -T _;
print "Binary\n" if -B _;
從 Perl 5.10.0 開始,作為純粹語法糖的一種形式,您可以堆疊檔案測試算子,以 -f -w -x $file
等同於 -x $file && -w _ && -f _
的方式。(這只是花俏的語法:如果您使用 -f $file
的傳回值作為另一個檔案測試算子的引數,不會發生任何特殊魔法。)
可攜性問題:perlport 中的「-X」。
為了避免讓程式碼的潛在使用者混淆於神秘的語法錯誤,請在腳本的最上方加上類似以下的內容
use v5.10; # so filetest ops can stack