十三、linux编程中目录IO常用编程函数
概念:
????????索引節(jié)點(diǎn),Inode是Index Node的縮寫(xiě),存儲(chǔ)于文件系統(tǒng)上的任何文件都可以用索引節(jié)點(diǎn)來(lái)表示,所以也可以說(shuō)索引節(jié)點(diǎn)是整個(gè)linux文件系統(tǒng)的基礎(chǔ)。操作系統(tǒng)在讀取硬盤(pán)的時(shí)候不是一個(gè)塊一個(gè)塊的來(lái)讀取信息,因?yàn)檫@樣做的話效率太低,文件數(shù)據(jù)都儲(chǔ)存在“塊”中,那么很顯然,我們還必須找到一個(gè)地方儲(chǔ)存文件的元信息,比如文件的創(chuàng)建者、文件的創(chuàng)建日期、文件的大小等等。這種儲(chǔ)存文件元信息的區(qū)域就叫做inode,中文譯名為“索引節(jié)點(diǎn)”。
????????在Linux系統(tǒng)中,文件系統(tǒng)主要分為兩部分,一部分為元數(shù)據(jù)(metadata),另一部分為數(shù)據(jù)本身。元數(shù)據(jù),換句話說(shuō),就是包含了數(shù)據(jù)有關(guān)信息的數(shù)據(jù)。索引節(jié)點(diǎn)就管理著文件系統(tǒng)中元數(shù)據(jù)的部分。
一、stat函數(shù)組(獲取文件信息,具體看stat結(jié)構(gòu)體 )
1、頭文件、函數(shù)原型及相關(guān)結(jié)構(gòu)體(可以通過(guò)man 2 stat 打開(kāi)對(duì)應(yīng)的stat幫助文檔)
/*所需頭文件*/ #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> /*函數(shù)原型*/ int stat(const char *path, struct stat *buf); – 參數(shù)*path:文件路徑 – 參數(shù)*buf:文件信息 – 返回值:成功為0,否則為-1 int fstat(int fd, struct stat *buf); – 參數(shù)fd:文件描述符 – 參數(shù)*buf:文件信息 – 返回值:成功為0,否則為-1 int lstat(const char *path, struct stat *buf); – 參數(shù)*path:文件路徑 – 參數(shù)*buf:返回文件的信息,針對(duì)符號(hào)鏈接,lstat 返回鏈接本身,而不是而非目標(biāo)文件 – 返回值:成功為0,否則為-1stat結(jié)構(gòu)體包含對(duì)象:struct stat {dev_t st_dev; /* ID of device containing file */ino_t st_ino; /* inode number */mode_t st_mode; /* protection */nlink_t st_nlink; /* number of hard links */uid_t st_uid; /* user ID of owner */gid_t st_gid; /* group ID of owner */dev_t st_rdev; /* device ID (if special file) */off_t st_size; /* total size, in bytes */blksize_t st_blksize; /* blocksize for file system I/O */blkcnt_t st_blocks; /* number of 512B blocks allocated */time_t st_atime; /* time of last access */time_t st_mtime; /* time of last modification */time_t st_ctime; /* time of last status change */};2、具體使用方法及代碼:?
#include <stdio.h> //通過(guò)man文檔可以查看到stat函數(shù)組頭文件 #include <sys/types.h> #include <sys/stat.h> #include <unistd.h>//open函數(shù)的參數(shù)頭文件 #include <fcntl.h>int main(int argc,char *argv[]) {struct stat groupstat;int fd,ret;if(argc <2){printf("\nPlease input file path\n");return 1;}//stat函數(shù)測(cè)試 ret = stat(argv[1],&groupstat);if(ret){printf("Please make sure file path\n");return 1;}printf("stat function test , %s of st_ino inode is %ld\n",argv[1],groupstat.st_ino);//fstat函數(shù)測(cè)試fd = open(argv[1],O_RDWR|O_NOCTTY|O_NDELAY);if(fd<0){printf("Please make sure file path\n");return 1;}ret = fstat(fd,&groupstat);if(ret){printf("Please make sure file path\n");return 1;}printf("fstat function test , %s of st_ino inode is %ld\n",argv[1],groupstat.st_ino);//lstat函數(shù)測(cè)試 ret = lstat(argv[1],&groupstat);if(ret){printf("Please make sure file path\n");return 1;}printf("lstat function test , %s of st_ino inode is %ld\n",argv[1],groupstat.st_ino);return 0; }二、chmod函數(shù)組(設(shè)置文件權(quán)限 )
1、頭文件、函數(shù)原型及相關(guān)結(jié)構(gòu)體(可以通過(guò)man 2 chmod打開(kāi)對(duì)應(yīng)的chmod幫助文檔)
/*頭文件*/ #include <sys/stat.h> /*函數(shù)原型*/ int chmod(const char *path, mode_t mode);// 修改指定路徑的文件權(quán)限 – 參數(shù)*path:文件路徑。 – 參數(shù)mode:直接使用數(shù)字即可。和前面命令中chmod 777 xxx 中的777 這個(gè)參數(shù)含義類(lèi)似,也可以使用文檔中的組合值。 – 返回值:成功返回0,錯(cuò)誤返回-1。 int fchmod(int fd, mode_t mode);// 修改打開(kāi)的文件權(quán)限 – 參數(shù)fd:文件描述符。 – 參數(shù)mode:直接使用數(shù)字即可。和前面命令中chmod 777 xxx 中的777 這個(gè)參數(shù)含義類(lèi)似,也可以使用文檔中的組合值。 – 返回值:成功返回0,錯(cuò)誤返回-1。2、具體使用方法及代碼:?
#include <stdio.h>#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>int main(int argc,char *argv[]) {int fd,ret;if(argc <3){printf("\nPlease input file path\n");return 1;}//chmod函數(shù)測(cè)試 ret = chmod(argv[1],0777);if(ret<0){printf("Please make sure file path\n");return 1;}printf("chmod %s 0777 is success!\n",argv[1]);//fchmod函數(shù)測(cè)試 fd = open(argv[2],O_RDWR|O_NOCTTY|O_NDELAY);if(fd<0){printf("Please make sure file path\n");return 1;}ret = fchmod(fd,0555);if(ret<0){printf("Please make sure file path\n");return 1;}printf("fchmod %s 0555 is success!\n",argv[1]);return 0; }三、獲取當(dāng)前目錄
1、頭文件、函數(shù)原型及相關(guān)結(jié)構(gòu)體(可以通過(guò)man 3 getcwd打開(kāi)對(duì)應(yīng)的getcwd幫助文檔)
/*頭文件*/ #include <unistd.h> /*函數(shù)原型*/ char *getcwd(char *buf, size_t size); – 參數(shù)*buf:保存當(dāng)前目錄的緩沖區(qū) – 參數(shù)size:在現(xiàn)代linux 中,buf 的長(zhǎng)度至少可以為255 字節(jié) – 返回值:成功返回指向當(dāng)前目錄的指針,和buf 的值一樣,錯(cuò)誤返回NULL char *getwd(char *buf); – 參數(shù)*buf:保存當(dāng)前目錄的緩沖區(qū) – 返回值:成功返回指向當(dāng)前目錄的指針,和buf 的值一樣,錯(cuò)誤返回NULL char *get_current_dir_name(void); – 參數(shù):無(wú) – 返回值:成功返回指向當(dāng)前目錄的指針,錯(cuò)誤返回NULL2、具體使用方法及代碼:?
#include <stdio.h> /*getcwd、getwd和get_current_dir_name 函數(shù)的頭文件*/ #define __USE_GNU #include <unistd.h>#define LENTH 255 int main() {char pwd[LENTH];char *wd; //getcwd函數(shù)測(cè)試 if(!getcwd(pwd,LENTH)){perror("getcwd");return 1;}printf("\ngetcwd pwd is %s\n",pwd);//getwd函數(shù)測(cè)試wd = getwd(pwd);if(!wd){perror("getcwd");return 1;}printf("\ngetwd pwd is %s\n",wd);//get_current_dir_name函數(shù)測(cè)試 wd = get_current_dir_name();if(!wd){perror("getcwd");return 1;}printf("\nget_current pwd is %s\n",wd);return 0; }四、創(chuàng)建目錄
1、頭文件、函數(shù)原型及相關(guān)結(jié)構(gòu)體(可以通過(guò)man 2 mkdir打開(kāi)對(duì)應(yīng)的mkdir幫助文檔)
/*頭文件*/ #include <sys/stat.h> #include <sys/types.h> /*函數(shù)原型*/ int mkdir(const char *pathname, mode_t mode); – 參數(shù):文件路徑 – 參數(shù)mode:直接使用數(shù)字即可。和前面命令中chmod 777 xxx 中的777 這個(gè)參數(shù)含義類(lèi)似,也可以使用文檔中的組合值。 – 返回值:成功返回0,錯(cuò)誤返回-1。2、具體使用方法及代碼:??
#include <stdio.h> //mkdir函數(shù)頭文件 #include <sys/stat.h> #include <sys/types.h>int main(int argc,char *argv[]) {int ret;//檢測(cè)參數(shù) if(argc <2){printf("\nPlease input file path\n");return 1;} //使用mkdir函數(shù)新建目錄ret = mkdir(argv[1],0777);if(ret<0){printf("mkdir %s failed!\n",argv[1]);return 1;}printf("mkdir %s suceces!\n",argv[1]);return 0; }五、刪除目錄
1、頭文件、函數(shù)原型及相關(guān)結(jié)構(gòu)體(可以通過(guò)man 2 rmdir打開(kāi)對(duì)應(yīng)的rmdir幫助文檔)
/*頭文件*/ #include <unistd.h> /*函數(shù)原型*/ int rmdir(const char *pathname); – 參數(shù)*pathname:文件和目錄的路徑 – 返回值:成功返回0,錯(cuò)誤返回-12、具體使用方法及代碼:??
#include <stdio.h> //rmdir函數(shù)頭文件 #include <unistd.h>int main(int argc,char *argv[]) {int ret;//檢測(cè)參數(shù) if(argc <2){printf("\nPlease input file path\n");return 1;} //使用rmdir函數(shù)刪除目錄ret = rmdir(argv[1]);//目錄要是絕對(duì)目錄if(ret<0){printf("rmdir %s failed!\n",argv[1]);return 1;}printf("rmdir %s suceces!\n",argv[1]);return 0; }六、改變當(dāng)前工作目錄
1、頭文件、函數(shù)原型及相關(guān)結(jié)構(gòu)體(可以通過(guò)man 2 chdir打開(kāi)對(duì)應(yīng)的chdir幫助文檔)
在實(shí)際應(yīng)用中,代碼可能需要從當(dāng)前目錄中進(jìn)到其它目錄,這個(gè)時(shí)候首先需要使用 getcwd函數(shù)獲取當(dāng)前目錄,保存起來(lái),然后使用 chdir 跳到其它目錄,完成操作,然后再使用 chdir回到最初保存的目錄。
#include <unistd.h> /*函數(shù)原型*/ int chdir(const char *path);- 參數(shù) *path:文件路徑- 返回值:成功返回 0,錯(cuò)誤返回-1。 int fchdir(int fd);- 參數(shù) fd:open 函數(shù)返回的句柄,文件描述符。- 返回值:成功返回 0,錯(cuò)誤返回-1。2、具體使用方法及代碼:?
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> //chdir和fchdir函數(shù)頭文件 #include <unistd.h>#define LENTH 255int main(int argc,char *argv[]) {int ret;char pwd[LENTH];//檢測(cè)參數(shù) if(argc <3){printf("\nPlease input file path\n");return 1;}//getcwd函數(shù)獲取當(dāng)前目錄 if(!getcwd(pwd,LENTH)){perror("getcwd");return 1;}printf("\ngetcwd pwd is %s\n",pwd);//使用chdir函數(shù)轉(zhuǎn)入其他目錄ret = chdir(argv[1]);if(ret){printf("Please make sure file path\n");return 1;}printf("chdir %s is success!\n",argv[1]);//轉(zhuǎn)入其他目錄,完成操作 //使用rmdir函數(shù)刪除目錄ret = rmdir(argv[2]);if(ret<0){printf("rmdir %s failed!\n",argv[2]);return 1;}printf("rmdir %s is success!\n",argv[2]);//再次使用chdir回到pwd保存的目錄ret = chdir(pwd);if(ret){printf("Please make sure file path\n");return 1;}printf("chdir %s is success!\n",pwd);return 0; }七、opendir和closedir目錄
1、頭文件、函數(shù)原型及相關(guān)結(jié)構(gòu)體(可以通過(guò)man 3 opendir(closedir)打開(kāi)對(duì)應(yīng)的opendir(closedir)幫助文檔)
前面介紹open和close函數(shù)用于打開(kāi)關(guān)閉文件,這里介紹的opendir和closedir用于打開(kāi)目錄,相當(dāng)于ls命令。
#include <sys/types.h> #include <dirent.h> /*函數(shù)原型*/ DIR *opendir(const char *name); – 參數(shù):目錄的路徑。 – 返回值:成功返回指向目錄流的指針,錯(cuò)誤返回NULL int closedir(DIR *dirp); – 參數(shù):opendir 返回的dir 指針 – 返回值:成功返回0, 失敗返回-12、具體使用方法及代碼:?
#include <stdio.h> //opendir和closedir函數(shù)頭文件 #include <dirent.h> #include <sys/types.h>int main(int argc,char *argv[]) {int ret;DIR *dir;//檢測(cè)參數(shù) if(argc <2){printf("\nPlease input file path\n");return 1;} //使用opendir函數(shù)打開(kāi)目錄dir = opendir(argv[1]);if(dir==NULL){printf("opendir %s failed!\n",argv[1]);return 1;}printf("opendir %s suceces!\n",argv[1]); //使用closedir函數(shù)關(guān)閉目錄closedir(dir);return 0; }八、readdir讀取目錄信息
1、頭文件、函數(shù)原型及相關(guān)結(jié)構(gòu)體(可以通過(guò)man 3 readdir打開(kāi)對(duì)應(yīng)的readdir幫助文檔)
在前面使用opendir打開(kāi)目錄的基礎(chǔ)上,可以使用readdir讀取目錄信息。
#include <dirent.h> /*函數(shù)原型*/ struct dirent *readdir(DIR *dirp); – 參數(shù)dirp:opendir 函數(shù)打開(kāi)目錄后返回的文件指針。 – 返回值:成功返回指向dirp 的指針dirent ,錯(cuò)誤返回NULL。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 */};2、具體使用方法及代碼:??
#include <stdio.h> //opendir,closedir,readdir函數(shù)頭文件 #include <dirent.h> #include <sys/types.h>int main(int argc,char *argv[]) {int ret;DIR *dir;struct dirent *catlog; //檢測(cè)參數(shù) if(argc <2){printf("\nPlease input file path\n");return 1;} //使用opendir函數(shù)打開(kāi)目錄dir = opendir(argv[1]);if(dir==NULL){printf("opendir %s failed!\n",argv[1]);return 1;}printf("opendir %s suceces!\n",argv[1]); //使用readdir讀取目錄argv[1]catlog = readdir(dir);if(catlog == NULL){printf("readdir %s failed!\n",argv[1]);return 1;}printf("%s d_ino is %ld\n ",argv[1],catlog->d_ino); //使用closedir函數(shù)關(guān)閉目錄closedir(dir);return 0; }九、硬鏈接和軟鏈接(符號(hào)鏈接)
1、硬鏈接
????????在Linux系統(tǒng)中,多個(gè)文件名指向同一索引節(jié)點(diǎn)(Inode)是正常且允許的。一般這種鏈接就稱(chēng)為硬鏈接。硬鏈接的作用之一是允許一個(gè)文件擁有多個(gè)有效路徑名,這樣用戶就可以建立硬鏈接到重要的文件,以防止“誤刪”源數(shù)據(jù)。(換句話說(shuō)就是我們前面講得,文件的屬性和數(shù)據(jù)是分開(kāi)的,將兩份不一樣的文件屬性同時(shí)指向同一份文件數(shù)據(jù)。那么這兩份文件屬性就是硬鏈接。)
硬鏈接函數(shù)
? int link(const char *oldpath, const char *newpath)
– 參數(shù)*oldpath:已有的文件路徑。
– 參數(shù)*newpath:新建的硬鏈接文件路徑。
– 返回值:成功返回0,錯(cuò)誤返回-1。
2、軟鏈接
????????軟鏈接(也叫符號(hào)鏈接),類(lèi)似于windows系統(tǒng)中的快捷方式,與硬鏈接不同,軟鏈接就是一個(gè)普通文件,只是數(shù)據(jù)塊內(nèi)容有點(diǎn)特殊,文件用戶數(shù)據(jù)塊中存放的內(nèi)容是另一文件的路徑名的指向,通過(guò)這個(gè)方式可以快速定位到軟連接所指向的源文件實(shí)體。軟鏈接可對(duì)文件或目錄創(chuàng)建。
軟鏈接函數(shù)
? int symlink(const char *oldpath, const char *newpath)
– 參數(shù)*oldpath:已有的文件路徑
– 參數(shù)*newpath:新建的符號(hào)鏈接文件路徑
– 返回值:成功返回0,錯(cuò)誤返回-1
3、解除鏈接
解除鏈接函數(shù)
? int unlink(const char *pathname)
– 參數(shù)*pathname:鏈接文件的路徑
– 返回值:成功返回0,錯(cuò)誤返回-1
– unlink指向軟鏈接,刪除軟鏈接;指向最后一個(gè)硬鏈接,相當(dāng)于刪除文件。因?yàn)橛叉溄拥奈募?shù)據(jù)至少要有一個(gè)硬鏈接,如果最后一個(gè)都被刪除,那么相當(dāng)于文件數(shù)據(jù)也要?jiǎng)h除了。
十、文件拷貝
????????linux中,沒(méi)有專(zhuān)用的文件拷貝函數(shù),而是通過(guò)從舊文件讀取(read函數(shù)),寫(xiě)入(write函數(shù))新文件,來(lái)實(shí)現(xiàn)文件的拷貝。
#include <stdio.h>#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <string.h>//argv[1] is oldpath ; argv[2] is newpath #define LENTH 1024 int main(int argc,char *argv[]) {int fds,fdt;char buffer[LENTH];char *fileold,*filenew;fileold = argv[1];filenew = argv[2];if(argc <3){printf("\nPlease input file path\n");return 1;}//打開(kāi)oldpath fds = open(fileold,O_RDWR);if(fds<0){printf("Please make sure file path\n");return 1;}//打開(kāi)newpath,如果沒(méi)有則創(chuàng)建目標(biāo)文件fdt = open(filenew,O_WRONLY|O_CREAT);if(fdt<0){printf("Please make sure file path\n");return 1;}//讀和寫(xiě)操作while(read(fds,buffer,LENTH)){write(fdt,buffer,strlen(buffer));}//關(guān)閉文件close(fds);close(fdt);printf("cp to finished!\n");printf("cp %s to %s success!\n",fileold,filenew);return 0; }十一、文件移動(dòng)
移動(dòng)文件命令為mv,函數(shù)為rename。
文件移動(dòng)函數(shù):
int rename(const char *oldpath, const char *newpath)
– 參數(shù)*oldpath:舊的文件路徑
– 參數(shù)*newpath:新的文件路徑
– 返回值:成功返回0,錯(cuò)誤返回-1
總結(jié)
以上是生活随笔為你收集整理的十三、linux编程中目录IO常用编程函数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 十二、Linux系统编程中man命令的使
- 下一篇: 十四、Linux进程编程