目錄的操作不論是在嵌入式還是應用軟件編程都是必不可少的,不同的開發語言可能略有不同,本章節主要是討論在Linux系統下目錄的一系列操作,以我的個人經驗,創建目錄和列出目錄中的文件這兩個功能用得最多。
一、獲取當前工作目錄
在shell中我們可以直接輸入命令pwd來顯示當前的工作目錄,在C程序中調用getcwd函數可以獲取當前的工作目錄。函數聲明:
char * getcwd(char * buf,size_t size);
getcwd函數把當前工作目錄存入buf中,如果目錄名超出了參數size長度,函數返回NULL,如果成功,返回buf。例如:
char strpwd[301];
memset(strpwd,0,sizeof(strpwd))
getcwd(strpwd,300);
printf("當前目錄是:%s\n",strpwd);
二、切換工作目錄
函數聲明:
int chdir(const char *path);
就像我們在shell中使用cd命令切換目錄一樣,在C程序中使用chdir函數來改變工作目錄。
返回值:0-切換成功;非0-失敗。
三、目錄的創建和刪除
在shell中可以通過mkdir/rmdir命令來創建/刪除目錄,C程序中用mkdir/rmdir函數來創建/刪除目錄。
創建目錄函數的聲明:
int mkdir(const char *pathname, mode_t mode);
mode的含義將按open系統調用的O_CREAT選項中的有關定義設置,當然,它還要服從umask的設置況,是不是看不明白?那先固定填0755,注意,0不要省略哦,它表示八進制。 例如:
mkdir("/tmp/aaa",0755); // 創建/tmp/aaa目錄
刪除目錄函數的聲明:
int rmdir(const char *pathname);
四、獲取目錄中的文件列表
在實際開發中,文件是存放在目錄中的,在處理文件之前,必須先知道目錄中有哪些文件,所以要獲取目錄中的文件列表。涉及到的庫函數如下:
1、包含頭文件
#include <dirent.h>
2、相關的庫函數
打開目錄的函數opendir的聲明:
DIR *opendir(const char *pathname);
讀取目錄的函數readdir的聲明:
struct dirent *readdir(DIR *dirp);
關閉目錄的函數closedir的聲明:
int closedir(DIR *dirp);
3、數據結構
1)目錄指針DIR
DIR *目錄指針名;
2)struct dirent結構體
每調用一次readdir函數會返回一個struct dirent的地址,存放了本次讀取到的內容,它的原理與fgets函數讀取文件相同。
struct dirent
{
long d_ino; // inode number 索引節點號
off_t d_off; // offset to this dirent 在目錄文件中的偏移
unsigned short d_reclen; // length of this d_name 文件名長
unsigned char d_type; // the type of d_name 文件類型
char d_name [NAME_MAX+1]; // file name文件名,最長255字符
};
我們只需要關注結構體的d_type和d_name成員,其它的不必關心。
d_name文件名或目錄名。
d_type描述了文件的類型,有多種取值,最重要的是8和4,8-常規文件(A regular file);4-目錄(A directory),其它的暫時不關心。
4、讀取目錄
示例(book123.cpp)
/*
* 程序名:book123.c,此程序用於演示讀取目錄下的文件名信息
* 作者:C語言技術網(www.freecplus.net) 日期:20190525
*/
#include <stdio.h>
#include <dirent.h>
int main(int argc,char *argv[])
{
if (argc != 2) { printf("請指定目錄名。\n"); return -1; }
DIR *dir; // 定義目錄指針
// 打開/tmp目錄
if ( (dir=opendir(argv[1])) == 0 ) return -1;
// 用於存放從目錄中讀取到的文件和目錄信息
struct dirent *stdinfo;
while (1)
{
// 讀取一條記錄並顯示到屏幕
if ((stdinfo=readdir(dir)) == 0) break;
printf("name=%s,type=%d\n",stdinfo->d_name,stdinfo->d_type);
}
closedir(dir); // 關閉目錄指針
}
運行效果
五、應用經驗
在實際開發中,對目錄的操作並不會像book123.c那樣簡單。
實際需求是這樣的,文件存放在某目錄中,該目錄下還會有多級子目錄,程序員想要的是列出該目錄及其子目錄下全部的文件名。
例如存在/home/wucz/tmp目錄,其子目錄結構和文件如下:
示例(book124.c)
/*
* 程序名:book124.c,此程序用於演示讀取目錄及其子目錄下全部的文件信息
* 作者:C語言技術網(www.freecplus.net) 日期:20190525
*/
#include <stdio.h>
#include <dirent.h>
// 列出目錄及子目錄下的文件
int ReadDir(const char *strpathname);
int main(int argc,char *argv[])
{
if (argc != 2) { printf("請指定目錄名。\n"); return -1; }
// 列出目錄及子目錄下的文件
ReadDir(argv[1]);
}
// 列出目錄及子目錄下的文件
int ReadDir(const char *strpathname)
{
DIR *dir; // 定義目錄指針
char strchdpath[256]; // 子目錄的全路徑
if ( (dir=opendir(strpathname)) == 0 ) return -1; // 打開目錄
struct dirent *stdinfo; // 用於存放從目錄讀取到的文件和目錄信息
while (1)
{
if ((stdinfo=readdir(dir)) == 0) break; // 讀取一記錄
if (strncmp(stdinfo->d_name,".",1)==0) continue; // 以.開始的文件不讀
if (stdinfo->d_type==8) // 如果是文件,顯示出來
printf("name=%s/%s\n",strpathname,stdinfo->d_name);
if (stdinfo->d_type==4) // 如果是目錄,再調用一次ReadDir
{
sprintf(strchdpath,"%s/%s",strpathname,stdinfo->d_name);
ReadDir(strchdpath);
}
}
closedir(dir); // 關閉目錄指針
}
運行效果
這才是程序員想要的結果。
在某些C語言的教材里,有遞歸函數這個概念,在我的教程里,沒有講這個概念,實際上,book124.c的ReadDir函數就是一個遞歸函數,在ReadDir函數中調用了自身。
六、課后作業
編寫示例程序,把本章節介紹的知識點全部演示一遍,用程序演示可以加深您的理解和映象。
七、版權聲明
C語言技術網原創文章,轉載請說明文章的來源、作者和原文的鏈接。
來源:C語言技術網(www.freecplus.net)
作者:碼農有道
如果文章有錯別字,或者內容有錯誤,或其他的建議和意見,請您留言指正,非常感謝!!!