8.熟悉了文件的一些基本操作,那么就要来理解文件的属性。比如前面我们做过cp命令的实现,前面我们所说的那些函数可以完成文件内容的复制,如果想获得某个文件的属性就要用到stat函数。
stat函数族可以将文件属性存储于struct stat类型的结构体中。需要注意的是这个结构体中的几个常用字段,比如st_ino是文件的索引节点编号;st_mode是文件的类型和访问权限,我们在open或chmod这个文件时候都会用到。
特别强调的是这个结构体中有三个关于时间的字段:st_atime表示文件最后一次被访问的时间;st_mtime表示文件最后一次被修改的时间,这里的修改特别指文件内容的修改;st_ctime也表示文件被修改的时间,但是更强调的是文件权限、所有者、所属组的修改时间。当然内容修改时,这个字段也会相应更新。
而且通过前面对ls命令以及cp命令的实现,我们可以发现,关于st_mode我们还有一些列的判定宏。比如S_ISLINK(st_mode),S_ISDIR(st_mode)等等。除此之外,我们还可以通过系统提供的几个访问权限宏与st_mode的与运算,可以具体的分解st_mode,比如:
if((st_mode&S_IROTH)==1) { printf("the file can be read by others\n!"); }
9.如何设置文件属性,这里涉及到一些常用函数。比如要修改文件的存取权限,就用chmod/fchmod函数;如果要修改文件的用户id和组id,那么就用chown组函数来进行相应修改。注意,如果只想修改两者中的一个,那么将两外一个的值指定为-1即可。
10.rename函数用来修改文件名或文件的位置,如果newpath所指定的文件已经存在,那么源文件会被删除。如果想删除一个文件,那么就直接调用remove函数即可。此函数既可以删除一个普通文件,也可是删除一个目录文件。这个函数其实是封装了unlink函数和rmdir函数。如果想创建一个目录则可以使用mkdir函数。
11.如何获得一个目录下的所有文件名称?下面这个例子是一个经典模型。
DIR *dir; struct dirent *ptr; if((dir=opendir(path))==NULL) { perror("opendir"); return -1; } while((ptr=readdir(dir))!=NULL) { printf("file name:%s\n",ptr->d_name); } /*do something*/ closedir(dir);
首先通过opendir打开一个目录,并返回一个DIR*的目录流dir,这类似于文件操作中的文件描述符(这里你可以理解为目录描述符)。然后将这个dir作为readdir函数的参数,使用一个while循环就可以依次获得该目录下的所有文件信息,存储于struct dirent类型的结构体中。
那么,如何根据上面的基本模型去实现其他的功能?你可以这么想:既然现在已经得到了每个文件的名称,那么想完成单个文件的操作就容易多了。