LINUX下历遍目录的方法一般是这样的 :
打开目录->读取->关闭目录
相关函数是
opendir -> readdir -> closedir
#include <dirent.h> DIR *opendir(const char *dirname);//打开目录,并返回句柄 struct dirent *readdir(DIR *dirp);//读取句柄,返回dirent结构体 int closedir(DIR *dirp); //关闭句柄
telldir() //返回当前指针的位置,表示第几个元素
//dirent.h是用于目录操作的头文件,linux 默认在/usr/include目录下(会自动包含其他文件)
DIR结构体:
struct __dirstream { void *__fd; char *__data; int __entry_data; char *__ptr; int __entry_ptr; size_t __allocation; size_t __size; __libc_lock_define (, __lock) }; typedef struct __dirstream DIR;
dirent结构体:
struct dirent { long d_ino; off_t d_off; unsigned short d_reclen; char d_name [NAME_MAX+1]; };
- d_ino存放的是该文件的索引节点号inode;
- d_off 是文件在目录中的编移,具体是什么意思也不是很明白,很少用到它,
- 基本上就是用到d_name
- short d_reclen是这个文件的长度,需要注意的是这里的长度并不是指文件大小,因为大小和长度是两回回事了,你可以用lseek将文件长度移得很长,但大小其实还是那么大。
- 最后一个元素就是我们要的了,文件名称。
使用dirent:
1.删除文件夹下所有文件
DIR *foder = opendir(file_path_to_delete.c_str()); struct dirent *next_file; char filepath[256]; while ((next_file = readdir(foder)) != NULL) { // build the path for each file in the folder sprintf(filepath, "%s/%s", course_path.c_str(), next_file->d_name); remove(filepath); }
注意:
路径要以’/’结尾:
file_path_to_delete += "\/";
通过readdir函数读取到的文件名存储在结构体dirent的d_name成员中,而函数
int stat(const char *file_name, struct stat *buf);的作用就是获取文件名为d_name的文件的详细信息,存储在stat结构体中。
stat结构体:
struct stat { mode_t st_mode; //文件访问权限 ino_t st_ino; //索引节点号 dev_t st_dev; //文件使用的设备号 dev_t st_rdev; //设备文件的设备号 nlink_t st_nlink; //文件的硬连接数 uid_t st_uid; //所有者用户识别号 gid_t st_gid; //组识别号 off_t st_size; //以字节为单位的文件容量 time_t st_atime; //最后一次访问该文件的时间 time_t st_mtime; //最后一次修改该文件的时间 time_t st_ctime; //最后一次改变该文件状态的时间 blksize_t st_blksize; //包含该文件的磁盘块的大小 blkcnt_t st_blocks; //该文件所占的磁盘块 };
返回说明:
成功执行时,返回0。失败返回-1,errno被设为以下的某个值
EBADF: 文件描述词无效
EFAULT: 地址空间不可访问
ELOOP: 遍历路径时遇到太多的符号连接
ENAMETOOLONG:文件路径名太长
ENOENT:路径名的部分组件不存在,或路径名是空字串
ENOMEM:内存不足
ENOTDIR:路径名的部分组件不是目录文件和目录
1.判断是文件还是目录:
#include<iostream> int main(int argc,char* argv[]) { int i; struct stat buf; char * ptr; for(i=1;i<argc;i++) { if(lstat(argv[i],&buf)<0) { perror("错误原因是:"); continue; } if (S_ISREG(buf.st_mode)) ptr="普通文件"; if (S_ISDIR(buf.st_mode)) ptr="目录"; cout<<"参数为:"<<argv[i]<<"的标识是一个"<<ptr<<endl; } exit(0); }
解析:
文件类型:
普通文件---S_ISREG(); 目录文件---S_ISDIR(); 特殊的块设备文件---S_ISBLK(); 字符特殊文件--S_ISCHR(); 套接字(P O S I X . 1或S V R 4无此类型)---S_ISSOCK(); 管道或FIFO---S_ISFIFO(); 符号链接( P O S I X . 1或S V R 4无此类型)---S_ISLNK();
文件类型信息包含在stat结构的st_mode成员中,可以用如下的宏确定文件类型,这些宏是stat结构中的st_mode成员
enum { DT_UNKNOWN = 0, # define DT_UNKNOWN DT_UNKNOWN DT_FIFO = 1, # define DT_FIFO DT_FIFO DT_CHR = 2, # define DT_CHR DT_CHR DT_DIR = 4, # define DT_DIR DT_DIR DT_BLK = 6, # define DT_BLK DT_BLK DT_REG = 8, # define DT_REG DT_REG DT_LNK = 10, # define DT_LNK DT_LNK DT_SOCK = 12, # define DT_SOCK DT_SOCK DT_WHT = 14 # define DT_WHT DT_WHT };
#i nclude<sys/stat.h> int stat(const char *restrict pathname,struct stat *restrict buf); int fstat(int fields,struct stat *buf); int lstat(const char *restrict pathname,struct stat *restrict buf); 返回值:若成功则返回0,失败则返回-1 一旦给出pathname,stat函数就返回与此命名文件有关的信息结构,fstat函数获取已在描述符fields上打开文件的有关信息。 lstat函数类似于stat.但是当命名的文件是一个符号链接时,lstat返回该符号链接的有关信息,而不是由该符号链接引用文件 的信息。第二个参数buf是指针,它指向一个我们必须提供的结构,这些函数填写由buf指向的结构。该结构的实际定义可能随实现 有所不同.
最后,总结一下,想要获取某目录下(比如a目下)b文件的详细信息,我们应该怎样做?
- 首先,我们使用opendir函数打开目录a,返回指向目录a的DIR结构体c。
- 接着,我们调用readdir( c)函数读取目录a下所有文件(包括目录),返回指向目录a下所有文件的dirent结构体d。
- 然后,我们遍历d,调用stat(d->name,stat *e)来获取每个文件的详细信息,存储在stat结构体e中。
2.判断目录是否存在:
DIR *mydir = NULL; if((mydir= opendir(dir))==NULL)//判断目录 { int ret = mkdir(dir, MODE);//创建目录 MODE为创建目录是的模式 if (ret != 0) { return -1; } printf("%s created sucess!/n", dir); }
关于mkdir
函数原型:
int mkdir(const char *pathname, mode_t mode);
mkdir()函数以mode方式创建一个以参数pathname命名的目录,mode定义新创建目录的权限。
返回值:
若目录创建成功,则返回0;否则返回-1,并将错误记录到全局变量errno中。
mode方式:
S_IRWXU | 00700权限,代表该文件所有者拥有读,写和执行操作的权限 |
S_IRUSR(S_IREAD) | 00400权限,代表该文件所有者拥有可读的权限 |
S_IWUSR(S_IWRITE) | 00200权限,代表该文件所有者拥有可写的权限 |
S_IXUSR(S_IEXEC) | 00100权限,代表该文件所有者拥有执行的权限 |
S_IRWXG | 00070权限,代表该文件用户组拥有读,写和执行操作的权限 |
S_IRGRP | 00040权限,代表该文件用户组拥有可读的权限 |
S_IWGRP | 00020权限,代表该文件用户组拥有可写的权限 |
S_IXGRP | 00010权限,代表该文件用户组拥有执行的权限 |
S_IRWXO | 00007权限,代表其他用户拥有读,写和执行操作的权限 |
S_IROTH | 00004权限,代表其他用户拥有可读的权限 |
S_IWOTH | 00002权限,代表其他用户拥有可写的权限 |
S_IXOTH | 00001权限,代表其他用户拥有执行的权限 |
1 用 int access(const char *pathname, int mode); 判断有没有此文件或目录 --它区别不出这是文件还是目录
2 用 int stat(const char *file_name, struct stat *buf); 判断该文件或目录是否否存在 ;得到st_mode,然后判断是不是目录文件。
stat()系统调用看是否成功,不成功就不存在,成功判断返回的st_mode是否是一个文件夹。
********************************************************************
linux c关于目录是否存在,新建目录等操作
1. 创建目录
#include <sys/stat.h>
#include <sys/types.h>
int mkdir(const char *pathname, mode_t mode);
运用条件:只能在已存在的目录下建立一级子目录
返回值: 返回0表示成功,返回-1表述出错。
mode 表示新目录的权限,可以取以下值:
其中,mode就用0777,0755这种形式。
2. 判断一个目录是否存在
可以使用opendir来判断,这是比较简单的办法。
#include<stdio.h> #include<string.h> #include<errno.h> #include<unistd.h> #include<dirent.h> #include<sys/types.h> #include<sys/stat.h> extern int errno; #define MODE (S_IRWXU | S_IRWXG | S_IRWXO) int mk_dir(char *dir) { DIR *mydir = NULL; if((mydir= opendir(dir))==NULL)//判断目录 { int ret = mkdir(dir, MODE);//创建目录 if (ret != 0) { return -1; } printf("%s created sucess!/n", dir); } else { printf("%s exist!/n", dir); } return 0; } int mk_all_dir(char *dir) { bool flag = true; char *pDir = dir; while (flag) { char *pIndex = index(pDir, '/'); if (pIndex != NULL && pIndex != dir) { char buffer[512] = {0}; int msg_size = pIndex - dir; memcpy(buffer, dir, msg_size); int ret = mk_dir(buffer); if (ret < 0) { printf("%s created failed!/n", dir); } } else if (pIndex == NULL && pDir == dir) { printf("dir is not directory!/n"); return -1; } else if (pIndex == NULL && pDir != dir) { int ret = mk_dir(dir); if (ret < 0) { printf("%s created failed!/n", dir); } break; } pDir = pIndex+1; } return 0; } int main() { char buffer[512] = {0}; printf("please input path mane/n"); fgets(buffer, sizeof(buffer), stdin); char *pIndex = index(buffer, '/n'); if (pIndex != NULL) { *pIndex = '/0'; } printf("check path mane %s/n", buffer); int ret = mk_all_dir(buffer); if (ret < 0) { printf("% mkdir failed!/n", buffer); return -1; } return 0; }
https://github.com/tronkko/dirent/blob/master/include/dirent.h