只要是撰寫稍微大一點的程式,說真的很難避免掉一些檔案或目錄的操作,特別是檔案總管或FTP一類的程式更是會大量的使用。Tcl提供了數個非常容易使用而且功能強大的檔案系統操作命令,使用這些命令你可以很容易的維護檔案的屬性、目錄的列表或執行檔案複製、刪除或搬移...等等,甚至是用來寫個檔案總管也夠用了。這一篇文章將介紹cd、pwd、glob及file等4個Tcl裡很常用的檔案及目錄相關命令。
12.1 工作目錄操作
玩過Unix-like系統的人一定都會知道pwd及cd的功能,它們分別可以用來取得目前的工作目錄以及改變目前的工作目錄。在Tcl裡同樣也提供這兩個命令,而且功能也是相同的。pwd命令的語法:
pwd
pwd命令回傳目前的工作目錄,使用時不需要加任何參數。
cd命令的語法:
cd ?dirName?
cd命令用來切換目前的工作路徑到dirName指定的位置,dirName必需是一個存在的目錄,若dirName沒有指定則切換到家目錄。cd命令回傳空字串。
程式範例:
程式輸出:
/private/tmp /Users/dai
上面的程式輸出會根據正在使用的作業系統及狀況而有所差別。
12.2 目錄列表
Tcl使用glob命令來提供像dir或ls一樣的目錄列表命令,它的語法如下:glob ?switches? pattern ?pattern ...?
glob搜尋指定目錄下符合pattern的所有檔案及目錄,並以清單的方式回傳搜尋的結果。switches是選擇性的參數用來調整glob的功能,pattern是由關鍵字及特殊字元所組成的字串,它被用來比對搜尋的項目。以下是pattern可以使用的特殊字元:
? | 符合任意單一字元。 |
* | 符合任意長度的任意字元。 |
[chars] | 符合chars字元集合(字串)裡的任一字元。 |
\x | 符合字元x。 |
{a,b,...} | 符合任一大括號內的字串。 |
switches可以使用的參數如下:
-directory directory | 使用directory當成要搜尋的目標目錄,若沒有指定則使用目前的工作目錄。 |
-join | 以目錄分隔字元把所有的pattern組合為單一pattern,再執行搜尋。 |
-nocomplain | 如果glob命令執行時沒有找到任何檔案或目錄,它會抱怨找不到檔案。加上-nocomplain告訴glob不要產生抱怨訊息。 |
-path pathPrefix | 搜尋時把pathPrefix串接在pattern的開頭,且不解釋pathPrefix內的特殊字元。 |
-tails | 讓回傳的清單只包含檔名及目錄名稱而不包含路徑。 |
-types typeList | 限定搜尋的檔案類型,必需要為包含以下字元的清單:b(block special file)、c(character special file)、d(directory)、f(plain file)、l(symbolic link)、p(named pipe)、s(socket)、r(可讀)、w(可寫)、x(可執行)、readonly(唯讀)、hidden(隱藏檔)。 |
- - (短線間沒有空白) | switches的結束符號。 |
以下的範例在不同的電腦上可能會有不同的輸出,所以就不把輸出的結果打在文件上了,請大家自己試試看。
在Windows下列出c:/下所有的檔案及目錄:
在Linux下列出家目錄下所有的目錄:
在Linux下列出指定目錄下所有的MP3檔案:
在Windows下列出c:/mp3資料夾內的所有MP3檔案:
注意哦!! Tcl就算在Windows下目錄分隔的符號也要用「/」而不是「\」。
12.3 檔案及目錄基礎操作
file命令提供了一套檔案及目錄的處理功能,它讓你可以很輕鬆的執行檔案命名、刪除、搬移以及屬性設定...等操作。另外file也提供了數個檔案路徑相關的處理功能,例如:切割及組合檔案的路徑、讀取符號連結甚至是判別檔案所在的檔案系統...等等。在接下來的說明裡會常常出現「檔案路徑」這個名詞,如果沒有特別說明的話它是指檔案或目錄的路徑。□ 檔案及目錄複製
file copy提供了檔案及目錄複製的功能,它的語法如下:file copy ?-force? ?- -? source target
source是來源項目的檔案路徑,target是要複製的目的地。如果目的地已經有相同的項目,加上-force可以強迫覆蓋已經存在的項目,否則的話程式會產生錯誤。file copy有兩種運作模式:
- 如果target是一個已存在的目錄,那source會被複製到target目錄裡面。
- 如果target是一個不存在的檔案或目錄,那source被複製到target的父目錄下,並用target的檔名部份命名。
假設/tmp是一個已經存在的目錄,那下面的例子都會套用第一種運作模式:
假設b2.txt不存在。下面的例子都會套用第二種運作模式:
除了一次操作一個檔案外,file copy也允許你一次複製N個檔案。它的語法如下:
file copy ?-force? ?- -? source ?source ...? targetDir
source是要複製的來源,targetDir是要複製的目的地,所有的來源項目都會被複製到targetDir裡面。注意!! 在多個檔案的操作情況下,targetDir一定要是一個已經存在的目錄,否則程式會產生錯誤。-force同樣用來指定要複蓋已存在的項目。
程式範列:
□ 刪除檔案及目錄
file delete提供了檔案及目錄刪除的功能,它的語法如下:file delete ?-force? ?- -? pathname ?pathname ... ?
pathname是要刪除的項目,若要刪除的內容是目錄而且目錄裡還有其它的項目,指定-force表示要連同目錄裡的項目一併刪除。
程式範列:
□ 重新命名
file rename提供了檔案及目錄重新命名的功能,切確的說它的行為更像是檔案的搬移。事實上這個命令的用法和file copy是一樣的,只是file copy會保留來源項目,而file rename則會刪除來源的項目。它的語法也和file copy是一樣的:file rename ?-force? ?- -? source target file rename ?-force? ?- -? source ?source ...? targetDir
程式範列:
□ 建立檔案連結
file link提供了建立連結的功能,它的語法如下:file link ?-linktype? linkName ?target?
linkName是要建立的連結檔案,target是要連結的目標。如果沒有指定target的話,那file link會把linkName當成是一個已存在的連結檔案,然後回傳它的連結目標。linktype是要建立連結的種類, 它的值可以是「-symbolic」或「-hard」,預設是-symbolic。
Linux下的程式範列:
□ 讀取檔案連結
file readlink提供了讀取連結的功能,並回傳連結的目標路徑。它的語法如下:file readlink name
程式範例:
□ 建立目錄
file mkdir提供了建立目錄的功能。它的語法如下:file mkdir dir ?dir ...?
dir是要建立的目錄。如果要建立的目錄已經存在,file命令會產生錯誤。
程式範列:
□ 其它常用的操作
file exists可以用來判斷檔案或目錄是否存在,是的話回傳1,否則回傳0:file isdirectory 可以用來判斷某個檔案路徑是不是目錄,是的話回傳1,否則回傳0:
file isfile 可以用來判斷某個檔案路徑是不是檔案,是的話回傳1,否則回傳0:
file pathtype name :分析檔案路徑是absolute、relative還是volumerelative。
file size 回傳檔案或目錄所佔用的位元組數:
file type 可以取得檔案或目錄的類型,它的回傳值可能是:file、directory、characterSpecial、blockSpecial、fifo、link或是socket。
12.4 檔案名稱及路徑處理
file命令提供了數個與平台無關的檔案路徑操作功能,如果說你想要寫跨平台的程式,這些功能將會非常的管用,因為它們讓你不用在意路徑分隔是斜線、反斜線還是其它。注意!! 接下來說明的file命令都是對字串來操作,換句話說,就算檔案不是真的存在,這些命令同樣可以正常的運作。□ 取得檔案的副檔名
file extension分析檔案路徑,然後回傳副檔名的部份。程式的第2行路徑中並沒有包含副檔名,所以程式會輸出空字串。
程式輸出:
.txt
□ 取得檔案的父目錄
file dirname分析檔案路徑,然後回傳目錄的部份。程式的第一行因為沒有目錄的部份,所以會回傳「.」表示目前的目錄。
程式輸出:
. /Users
□ 取出檔案的檔名部份
file tail分析檔案路徑中的檔名部份,並回傳檔名部份。程式輸出:
a.txt
□ 移去檔案的副檔名
file rootname分析檔案路徑,然後回傳移去副檔名後的結果。程式輸出:
/Users/dai/a
□ 切割檔案路徑
file split切割檔案路徑並以清單的方式回傳切割後的結果。程式輸出:
/ Users dai a.txt
□ 組合檔案路徑
file join可以用來組合檔案路徑,並回傳組合後的結果。程式輸出:
/ Users/dai/a.txt
□ 正規化檔案路徑
file normalize會解析檔案路徑中的「..」及「.」符號,並回傳處理後的結果。程式輸出:
/a/b /a/b/c
□ 轉換路徑
file nativenam轉換檔案路徑為目前平台相依的格式。Linux及Mac下的程式輸出:
/Users/dai/a.txt
Windows下的程式輸出:
\Users\dai\a.txt
□ 取得路徑分隔符號
file separator傳回目前平台的路徑分隔符號。Linux及Mac下的程式輸出:
/
Windows下的程式輸出:
\
12.5 檔案及目錄的屬性處理
接下來要介紹檔案及目錄的屬性檔案。□ 存取時間屬性
file atime可以用來取得或是設定檔案或目錄的最後存取時間,回傳的時間是由1970/1/1開始算起的秒數。file mtime可以用來取得或是設定檔案或目錄的最後修改時間,回傳的時間是由1970/1/1開始算起的秒數。
程式第2行中的clock seconds會回傳自1970/1/1到目前的秒數。
□ 存取權限屬性
file attribute可以用來取得或是設定檔案的屬性。如果你要用attribute來取得所有可用的屬性可以這樣做:在我的Mac系統下它有如下的輸出:
-group staff -owner dai -permissions 00644 -readonly 0 -creator {} -type {} -hidden 0 -rsrclength 0
如果你要設定屬性可以這樣做:
file executable回傳檔案是否有可執行的權限。回傳1表示可執行,否則回傳0。
file readable回傳檔案或目錄是否有讀取的權限。回傳1表示可讀取,否則回傳0。
file writable回傳檔案或目錄是否有寫入的權限。回傳1表示可寫入,否則回傳0。
file owned name回傳檔案是否屬於目前使用者。回傳1表示是,否則回傳0。
□ 存取檔案的狀態
file lstat可以取得檔案的資訊,功能如同lstat系統乎叫。它的語法如下:file lstat name varName
file stat可以取得檔案的資訊,功能如同stat系統乎叫。它的語法如下:
file stat name varName
這兩個命令都會取得檔案或目錄name的狀態,並把取得的資訊以陣列的型式儲存在varName指定的變數裡。如下是取回的陣列元素:
atime | 檔案最後存取的時間。 |
ctime | 檔案狀態最後變更的時間。 |
dev | 檔案系統的裝置代號。 |
gid | 檔案所有群組的ID。 |
ino | i-node編號。 |
mode | 檔案屬性。 |
mtime | 檔案最後修改的時間。 |
nlink | 連結數量。 |
size | 檔案的大小。 |
type | 檔案的類型,和file type一樣。 |
uid | 檔案所有者的ID。 |
程式範例:
程式輸出:
data(ctime) = 1239428193 data(dev) = 234881026 data(gid) = 20 data(ino) = 192353 data(mode) = 16877 data(mtime) = 1239428193 data(nlink) = 42 data(size) = 1428 data(type) = directory data(uid) = 501
12.6 其它檔案處理功能
file channels可以列出已經開啟的檔案通道。它的語法如下:file channels ?pattern
file channels以清單的方式回傳符合pattern的通道代碼,如果不指定pattern的話會回傳所有的通道代碼。
file system用來分析檔案儲存在哪一種檔案系統下。
在Windows XP下,這個程式應該會輸出:
native NTFS
file volumes以清單的方式列出目前已掛載的檔案系統目錄
在我的Windows下它輸出了:
A:/ C:/ D:/ X:/
按右上方的「#」號切換側邊欄