1) fstat, stat, lstat 系統調用
#include
<unistd.h>
#include <sys/stat.h>
#include
<sys/types.h> // Linux系統不需要,UNIX需要
int fstat(int
fildes,struct stat *buf);
返迴文件描述符相關的狀態檔案的資訊,這些資訊被儲存在一個stat結構體中,stat結構體幾乎儲存了所有的檔案狀態資訊。
int stat(const char *path, struct stat *buf);
int lstat(const char
*path, struct stat *buf);
這兩個系統調用提供了一樣的結果,但是他們參數有些不同,他們接受一個路徑,而不是一個檔案描述符。另外
lstat和stat不一樣的是,假如讀取到了符號串連,lstat讀取符號串連本身的狀態資訊,而stat讀取的是符號串連指向檔案的資訊。
得到了stat的結構體指標,還需要瞭解如何使用它,首先來瞭解它的一些成員:
st_mode |
檔案的許可權資訊和類型資訊 |
st_ino |
檔案相關的inode |
st_dev |
文 件所屬的裝置 |
st_uid |
檔案所有者的ID |
st_gid |
檔案所有者的組ID |
st_atime |
檔案最後訪問時間 |
st_ctime |
檔案最後修改時間(修改許可權,使用者,組或者內容) |
st_mtime |
最後修改內容的時間 |
st_nlink |
硬串連的數母 |
由上表可見,stat結構體通過資訊的豐富,關於如何利用沒一個資訊,這不是本文的主題。最常用的就是st_mode成員了
為了方便的擷取檔案狀態資訊,定義了一些操作st_mode的宏:
S_ISDIR // 是不是目錄
S_IFBLK //
檔案是不是塊裝置
S_IFIFO // 檔案是不是FIFO(具名管道)
S_IFLNK // 檔案是不是符號串連
定義的宏還有很多,全面的介紹似乎不符合本文的主題,這就不說了。
2) opendir()
#include
<sys/types.h> // Linux系統不需要,UNIX需要
#include <dirent.h>
// dirent是directory entry的縮寫
DIR *opendir(const char *name);
通過路徑開啟一個目錄,返回一個DIR結構體指標(也叫做目錄流),和檔案描述符以及檔案流一樣,它是對應一個特定的目錄,並作為其他動作目錄的系統調用
的參數。系統調用失敗返回NULL。
3) readdir()
#include
<sys/types.h> // Linux系統不需要,UNIX需要
#include <dirent.h>
讀取目錄中的下一個目錄實體(directory entry),readdir(DIR
*)結構一個DIR結構體指標作為參數,返回一個dirent結構體指標,這個結構體的具體內容在:http://www.i170.com/user/killercat/Article_54617
的
最後一部分有描述過,包含了檔案名稱字(d_name成員)和
Inode(d_ino成員)。這個系統調用失敗或者沒有目錄實體可以讀取時,返回為NULL。
4) chdir()
#include <unistd.h> // 注意一下這個標頭檔和其他的不一樣
int chdir(const char
*path);
改變目錄。於使用者通過cd命令改變目錄一樣,程式也可以通過chdir來改變目錄,這樣使得
fopen(),opendir(),這裡需要路徑的系統調用,可以使用相對於目前的目錄的相對路徑開啟檔案(目錄)。
5)
closedir(DIR*)
#include <dirent.h>
#include
<sys/types.h> // Linux系統不需要,UNIX需要
關閉目錄流。
下面是遞迴的打出一個目錄下檔案的程式(出自《Linux 程式設計》英文版第3版):
#include <unistd.h>
#include <sys/stat.h>
#include <stdio.h>
#include
<string.h>
#include <stdlib.h>
#include
<dirent.h>
void printdir(char *dir, int depth){
DIR *dp;
struct dirent *entry;
struct stat statbuf;
if((dp = opendir(dir)) == NULL){
fprintf(stderr,"cannot open directory: %s/n",dir);
return;
}
chdir(dir);
while((entry = readdir(dp)) != NULL){
lstat(entry->d_name,&statbuf);
if(S_ISDIR(statbuf.st_mode)){
if(strcmp("..",entry->d_name) == 0||
strcmp(".",entry->d_name) == 0)
continue;
printf("%*s%s//n",depth,"",entry->d_name);
printdir(entry->d_name,depth+4);
}
else
printf("%*s%s/n",depth,"",entry->d_name);
}
chdir("..");
closedir(dp);
}
int main(){
printdir("/home",0);
}