前言:unix下一切東西都是文件,一共有7種不同的文件,前一篇博客已經講解的很清楚了,不懂的可以看看這里。當然,博主知道有些朋友比忙,沒時間看,那我就簡單點講講這7種文件都有哪些吧。
文件類型包括在stat結構的st_mode成員中,下面是這7種文件類型的判斷方法: |
當然這些文件都是有訪問權限的,很巧這些權限也是在一個叫struct stat這個結構體中
結構體struct stat中的成員st_mode值包含了對文件的訪問權限位,任何類型的文件都有訪問權限(access permission)。每個文件有9個訪問權限,可以它們分為3類,u表示用戶(所有者)、g表示組、o表示其他 st_mode屏蔽 含義 |
那么問題來了既然有權限,我們怎么知道這些權限呢?當然這不是難事,一個access函數就可以解決問題了
函數描述:按實際用戶ID和實際組ID進行訪問權限測試 |
這是access函數的具體用法的代碼(argv[1]必須是一個已經存在的文件):

#include <stdio.h> #include <unistd.h> #include <stdlib.h> int main(int argc,char **argv) { if(argc != 2) { printf("argc must equal to two!\n"); exit(1); } if(access(argv[1],F_OK)) //判斷文件是否存在 { printf("%s not existence!\n",argv[1]); exit(1); } if(access(argv[1],R_OK)) //判斷文件是否可讀 { printf("%s not read permission\n",argv[1]); } else { printf("%s have read permission\n",argv[1]); } if(access(argv[1],W_OK)) //判斷文件是否可寫 { printf("%s not write permission\n",argv[1]); } else { printf("%s have write permission\n",argv[1]); } if(access(argv[1],X_OK)) //判斷文件是否可執行 { printf("%s not execute permission\n",argv[1]); } else { printf("%s have execute permission\n",argv[1]); } return 0; }
在ubuntu下運行:
當然了既然有權限,那么我們在創建文件的時候文件權限也是可以自己控制的,umask函數用上場了
|
代碼的具體用法如下:

#include <sys/stat.h> #include <stdio.h> #include <sys/types.h> #include <fcntl.h> #include <stdlib.h> #define RRR (S_IRUSR|S_IRGRP|S_IROTH) //設置文件權限為用戶讀、組讀、其他讀 int main(int argc,char *argv[]) { umask(0); //不設置文件屏蔽字 creat("text",RRR); //以用戶讀、組讀、其他讀的權限創建文件text.txt //這里也可以用open umask(S_IRUSR|S_IRGRP); //創建用戶讀、組出屏蔽字 creat("text1",RRR); //最后創建出來的文件只有其他讀的權限 return 0; }
既然文件可以創建,當然目錄也是可以創建的,mkdir函數就是為創建目錄而生的:
函數描述:創建一個空目錄,.和..自動創建 S_IRWXU 用戶(所有者)、讀、寫和執行 S_IRWXO 其他讀、寫和執行 |
創建目錄的具體實現:

#include <sys/stat.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> int main(int argc,char *argv[]) { if(mkdir("test.txt",S_IWOTH|S_IRUSR|S_IRGRP) == -1) /*以其他寫、用戶讀、組讀權限創建一個空目錄*/ { perror("mkdir"); exit(1); } return 0; }
umask函數是在創建文時設置權限,那么在文件被創建之后還能修改權限嗎?這時候chmod函數就派上用處了
(1)頭文件 #include <sys/stat.h> (2)函數原型 int chmod(const char *path, mode_t mode); (3)參數: a、path:文件路徑 b、mode:跟上面midir函數中的成員mode一樣,其中的宏位或就可以了
|
改變文件權限的例子:
chmod("text",S_IRUSR|S_IRGRP|S_IROTH); //把text文件的權限改為用戶讀、組讀、其他讀
既然權限可以改變權限,當然改個名字也是沒問題的,用rename函數輕松解決問題:
(1)頭文件 #include <stdio.h> (2)函數原型 int rename(const char *old, const char *new); (3)參數: a、old:文件原來的名字 b、new:新的名字 (4)返回值: 成功:0 失敗:-1 |
改變文件名字的例子:
rename("text","hhtext"); //將名字為text的文件改為hhtext
其實文件中還有個小操作就是可以在任何位置截斷文件中的內容:
truncate("test",3); //將文件test長度截斷為3字節
好了講了那么多關於文件的權限的東西,是時候講講怎么打開一個目錄和讀目錄中的的東西了:
讀目錄中,要經過三步:打開目錄、讀目錄、關閉目錄,對應用到的函數分別為opendir、readdir、closedir。 一、打開目錄 (1)頭文件 #include <sys/types.h> #include <dirent.h> (2)函數原型 DIR *opendir(const char *name); (3)參數 name:目錄名 (4)返回值: 成功:返回一個DIR*型的目錄流 失敗:NULL 二、讀目錄 (1)頭文件 #include <dirent.h> (2)函數原型 struct dirent *readdir(DIR *dirp); (3)參數 a、dirp:調用opendir函數后返回的DIR*類型的目錄流 (4)返回值: 成功:返回一個(struct dirent)型的結構體 下面是struct dirent結構體的具體內容 struct dirent { ino_t d_ino; 節點號 /*inode number */ off_t d_off; 偏移到下一個方向 /* offset to the next dirent */ unsigned short d_reclen; 記錄長度 /* length of this record */ unsigned char d_type; 文件類型,不支持所有文件系統類型/* type of file; not supportedby all file system types */ char d_name[256]; 文件名 /* filename */ }; struct dirent中的成員d_type又有以下幾種類型: DT_BLK 塊設備 (This is a block device.) DT_CHR 字符設備(This is a character device.) DT_DIR 目錄( This is a directory.) DT_FIFO 命名管道或FIFO(This is a named pipe (FIFO).) DT_LNK 符號連接(This is a symbolic link.) DT_REG 普通文件(This is a regular file.) DT_SOCK UNIX域套接字( This is a UNIX domain socket.) DT_UNKNOWN 未知類型(The file type is unknown.) 讀完或者失敗都返回NULL 三、關閉目錄 (1)頭文件 #include <sys/types.h> #include <dirent.h> (2)函數原型 int closedir(DIR *dirp); (3)參數 a、dirp:用opendir函數后返回的DIR*類型的目錄流 (4)返回值: 成功:0 失敗:-1 四、更改當前工作路徑 (1)頭文件 #include <unistd.h> (2)函數原型 int chdir(const char *path); (3)參數: a、path:需要更改的路徑 (4)返回值 成功:0 失敗:-1 例子: chdir("/test.txt"); //當前工作目錄更改到test.txt中 五、獲得當前工作目錄完整的絕對路徑 (1)頭文件 #include <unistd.h> (2)函數原型 char *getcwd(char *buf, size_t size); (3)參數: a、buf:存放絕對路徑的緩沖區 b、size: 緩沖區的大小 (4)返回值: 成功:返回當前工作目錄完整的絕對路徑 失敗:NULL 例子: char buf[100]; bzero(buf,sizeof(buf)); if(getcwd(buf,sizeof(buf)) == NULL) { perror("getcwd"); exit(1); }
打開一個目錄然后讀目錄中的文件並把文件名打印出來,具體代碼如下:

#include <stdio.h> #include <sys/types.h> #include <dirent.h> #include <stdlib.h> #include <stdlib.h> #include <string.h> #include <unistd.h> void open_file(char *name) { DIR * entry; //opendir返回值 struct dirent *ep; //readdir返回值 char path_name[100]; if((entry = opendir(name)) == NULL) { perror("opendir"); exit(1); } while(1) { if((ep = readdir(entry)) == NULL) { break; } if(ep->d_name[0] == '.') //去掉隱藏文件 { continue; } sprintf(path_name,"%s/%s",name,ep->d_name); //拼接兩個字符 printf("%s\n",path_name); //輸出路徑 if(ep->d_type & DT_DIR) //目錄 也可以用lstat/stat函數 { open_file(path_name); //遞歸打開下一目錄 } } closedir(entry); } int main(int argc,char *argv[]) { if(argc != 2) { printf("argv[1] have to a directory!\n"); exit(1); } open_file(argv[1]); return 0; }
運行程序的效果圖如下:
最后來點小知識:
**每個文件系統所在的設備都有主、次設備號表示 |
具體代碼如下:

#include <sys/stat.h> #include <stdio.h> #include <errno.h> #include <stdlib.h> int main(int argc,char *argv[]) { int i; struct stat buf; for(i=1;i<argc;i++) { printf("%s:",argv[i]); if(stat(argv[i],&buf) == -1){ perror("stat"); exit(1); } printf("dev = %d/%d",major(buf.st_dev),minor(buf.st_dev)); //判斷是否是字特殊文件(S_ISCHR)塊特殊文件(S_ISCHR) if(S_ISCHR(buf.st_mode) || S_ISBLK(buf.st_mode)){ printf(" (%s) rdev = %d/%d", (S_ISCHR(buf.st_mode)) ? "character" : "block", major(buf.st_rdev),minor(buf.st_rdev)); } printf("\n"); } return 0; }
運行結果: