Perlchina提醒您:請保護(hù)作者的著作權(quán),維護(hù)作者勞動的結(jié)晶。
目錄 |
$path = "/path/to/dir/";opendir DIR, $path;@arr1 = readdir DIR;@arr2 = grep{-T "$path$_"} @arr1; #text files only@arr3 = grep{!-d "$path$_"} @arr1; #no directories@arr4 = grep{-s "$path$_" < 1024} @arr1; #less than 1K
代碼解釋:假如被測試的目錄項是一個文本文件,那么 -T 文件操作符就會返回真。其實(shí)針對目錄項的測試操作還有很多。(注:文件和目錄在系統(tǒng)中都是以目錄項的形式來管理的,所以要區(qū)別一個目錄項指向的是一個文件還是一個目錄需要相應(yīng)的操作符)。注意上面的 readdir 函數(shù)返回指定目錄下的所有目錄項。因為在 grep 函數(shù)中對目錄項的測試需要文件的完全路徑,所以我們把 $PATH(存儲了目錄項的部分路徑) 和 $_(存儲了目錄項的名字)中的內(nèi)容聯(lián)合起來得到文件的完全路徑
use File::Find;find(\&handleFind, ‘imac:documents:code‘);sub handleFind{my $foundFile = $File::Find::name;print "$foundFile\n" if ($foundFile =~ /\.html?$/i);}
運(yùn)行結(jié)果: imac:documents:code:index.html imac:documents:code:perl:example.HTM
代碼討論:那些工作于 Unix 系統(tǒng)的 Perl 程序員可以非常簡便的利用 UNIX 上提供的工具來完成許多日常的工作,比如遞歸的列出指定目錄下的所有目錄項(也就是列出指定目錄及指定目錄子目錄下的所有目錄項目)。然而 Perl 的一個最大的特征就是可以運(yùn)行于很多的平臺上。所以如果你碰巧工作在一個非 UNIX 的平臺,或者如果你雖工作在 UNIX 平臺,但不喜歡使用系統(tǒng)工具寫腳本,你可以選擇 Perl。要完成這些巧妙的工作,你需要使用 perl 中的 File:Find 模塊。當(dāng)你加載了這個模塊的時候,你就可以使用其中的 find 子函數(shù),在調(diào)用這個函數(shù)的時候,需要帶參數(shù):第一個參數(shù)是一個函數(shù)的引用,這個函數(shù)由你自己建立,每次一個文件被找到的時候,它都會運(yùn)行。接下來的一個參數(shù)是一串你想要搜索的路徑。我寫的這個示例腳本是運(yùn)行在 Macintosh OS 8.x 系統(tǒng)上的,所以我使用了 Mac 系統(tǒng)的路徑分隔符 :。如果是在 Windows,你可以用反斜杠,如果是在 Unix 系統(tǒng)則是正斜杠(至于在 Amiga 系統(tǒng)上用什么我就不知道了)??傊?,find 函數(shù)將會在每次找到一個文件的時候調(diào)用你給出的子函數(shù),而且會對子目錄進(jìn)行查找。在我的 handledfind 子函數(shù)中,我通過這個模塊特定變量 $File::Find::name 來獲得每次 find 找到的文件名。然后,就可以對該文件執(zhí)行任何你想的測試,在上面的例子中,我們輸出有 .html 的擴(kuò)展名文件名。
open FH, "< anthem";$/ = undef;$slurp = <FH>;print $slurp;
運(yùn)行結(jié)果:一下就顯示了所有的文件內(nèi)容,此刻你應(yīng)該非常的自豪。:) 代碼討論:尖括號 <> 對文件句柄進(jìn)行操作,在標(biāo)量上下文中它將返回文件的下一條記錄,在數(shù)組上下文中它將返回所有的記錄。在默認(rèn)的情況下,文件中的記錄被認(rèn)為是由換行符分開(例如回車或其他代表新行開始的字符)。你可以重新設(shè)定這個默認(rèn)的分隔符,然后 Perl 將會以你指定的分隔符為準(zhǔn)來替代換行符。全局變量 $/ 里存儲了輸入文件的分隔符,如果你把 $/ 的值設(shè)置為 undef ,那么 Perl 將會認(rèn)為整個文件是一條記錄(因為此刻已經(jīng)沒有文件分隔符了)。牢記 $/ 是全局變量,千萬不要在腳本的其他地方不經(jīng)意的改變它,這個錯誤將很難被發(fā)現(xiàn)。你可能會問,我們能否不改變 $/,而采用把文件的所有記錄讀到一個數(shù)組中,然后把數(shù)組聯(lián)合成一個很長的字符串(比如 $slurp = join("",<FH>);)的方法實(shí)現(xiàn)一次讀入文件。當(dāng)然這也是一個有效的解決辦法,但是你會發(fā)現(xiàn)它很慢,是否選用它取決你的應(yīng)用,取決于你是否關(guān)心運(yùn)行速度。
open(MYOUT, "> bottle.txt");*STDOUT = *MYOUT;print "message";
運(yùn)行結(jié)果:文本文件 bottle.txt 現(xiàn)在包含 message 字符串。代碼討論:以前可能你配合使用過 Print 函數(shù)和文件句柄,但是你是否知道就算你沒有使用文件句柄,Perl 也默認(rèn)你在使用一個稱為 STDOUT 的句柄?C 程序員知道 STDOUT 代表標(biāo)準(zhǔn)輸出,也就是通常的屏幕,或終端窗口(或者是 CGI 程序的輸出端 - 瀏覽器)。在這里我們完成的工作是創(chuàng)建我們自己的文件句柄,它指向一個給定的文件,然后我們做了一件比較鬼的工作,使用 * 前綴把 STDOUT 轉(zhuǎn)換為 typeglob 類型。Typeglob 類型的數(shù)據(jù)可以有別名,這樣一個變量可能會指向另一個其他名字的變量。上面第二行代碼使 STDOUT 指向 MYOUT 變量。所以執(zhí)行 print 操作時的默認(rèn)輸出對象也就成為了我們創(chuàng)建的文件句柄。
use IO::Tee;$tee = IO::Tee->new(">> debuglog.txt", \*STDOUT);print $tee "an error ocurred on ".scalar(localtime)."\n";
運(yùn)行結(jié)果:an error ocurred on Fri Feb 23 21:44:20 2001 代碼討論:如果,由于種種原因你想要同時向兩個位置寫入同一個字符串,這和 UNIX 下的 tee 工具的用途一樣。即使你不是工作在 Unix 平臺上,Perl 也通過 Tee 模塊為你提供這個功能。Tee 模塊可以在 CPAN 下載,你應(yīng)該把它安裝到 Perl 的 IO 庫文件夾中。Tee 模塊以 OOP 方式編寫,所以使用它之前你應(yīng)該首先使用它的 new 方法來創(chuàng)建一個 Tee 對象,整個過程需要兩個參數(shù),每個參數(shù)既可以是代表文件句柄的字符串,也可以是一個對已打開的文件句柄的引用。在上面的例子中,我們用一個字符串來代表一個以附加模式打開的文件句柄,它指向名為 debuglog.txt 的文件,另一個參數(shù)是系統(tǒng)內(nèi)置的文件句柄 STDOUT,整個句柄是系統(tǒng)自動創(chuàng)建的,print 函數(shù)默認(rèn)情況對它進(jìn)行操作。為了得到一個文件句柄的引用我們需要對一個 typeglob 類型的數(shù)據(jù)使用反斜杠。Typeglob 可以代表任何已命名的某個變量,不論它是數(shù)組,散列還是標(biāo)量等。使用 * 很有必要,因為文件句柄自己沒有前綴符號。new 操作符返回 Tee 類的一個實(shí)例對象,然后我們把整個實(shí)例賦給 $tee 標(biāo)量?,F(xiàn)在,無論什么時候我們向 $tee 進(jìn)行寫入操作,我們都同時向兩個位置進(jìn)行寫操作。
use File::Basename;$path = "/docs/sitecircus.com/html/tricks/trick.of.the.week.html";$basename = basename($path, ".html");print $basename;
運(yùn)行結(jié)果:trick.of.the.week 代碼討論:好了,成功了。問題是要找出文件的名字,要不帶任何路徑前綴,不帶任何擴(kuò)展名。File::Basename 模塊可以使這很容易實(shí)現(xiàn),我們只需要把文件的完全路徑還有要剔除的擴(kuò)展名傳給它。上面的 path 變量是文件的完全路徑,注意文件分隔符是 /,這個字符很特殊,因為它是操作系統(tǒng)的保留字符。這里你不能在文件名里使用系統(tǒng)的分隔符。你應(yīng)該知道當(dāng)今流行的操作系統(tǒng)都使用自己獨(dú)特的文件分隔符:Unix使用 /,Windows 使用 \,Macintosh 使用 :(順便說一下,在 Windows 上的 Perl 腳本中,你既可以使用 \也可以使用 /作為文件分隔符,Perl 的解釋器能理解你的意思)。File::Basename,當(dāng)然,能正確在完全路徑中找到文件名,不論時在什么系統(tǒng)下。
($uid, $gid) = (getpwnam($username))[2,3]or die "$user not in passwd file";chown ($uid, $gid, $file)or warn "couldn‘t chown $file.";
運(yùn)行結(jié)果:無輸出代碼討論:有的時候,你可能知道一個用戶名,而你想用這個用戶名做些事,比如改變一個文件的所有者。但是不幸的是,Perl 的 chown 命令不能接受用戶名作為參數(shù),但是可以接受一對數(shù)字:userid 和 groupid。雖然有這些不便之處,Perl 并沒有讓我們陷入困境,我們可以把用戶名作為 getpwnam 函數(shù)的參數(shù),獲得一個數(shù)組,里面包含了用戶名對應(yīng)的 userid 和 groupid,分別對應(yīng)著數(shù)組里的第二和第三個元素。
作者:Luke Melia