-X FILEHANDLE
-X EXPR
-X DIRHANDLE
-X

檔案測試,其中 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_CTYPEuse locale 範圍內執行,奇怪的字元就是任何在目前區域設定中無法列印或不是空白的字元。)如果在檔案處理上使用 -T-B,會檢查目前的 IO 緩衝區,而不是第一個區塊。-T-B 都會在空檔案或測試檔案處理時檔案在 EOF 時傳回 true。由於您必須讀取檔案才能執行 -T 測試,因此在大部分情況下,您會想要先對檔案使用 -f,例如 next unless -f $file && -T $file

如果任何檔案測試(或 statlstat 算子)給予由單一底線組成的特殊檔案處理,則會使用前一個檔案測試(或 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