需求:在linux下遍历目录,输出目录中各文件名。
在linux下遍历目录的相关函数有:
#include <dirent.h>
DIR* opendir(const char* dir_path);
struct dirent* readdir(DIR* dirp);
int closedir(DIR* dirp);
int lstat(const chat* filename,struct stat* st);
在这里涉及到几个结构体:DIR,struct dirent,struct stat:
DIR结构体是一个内部结构,类似与FILE,用来保存当前被读取的目录的信息:
truct __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;
struct dirent,指向文件夹下的目录内容:
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 (null-terminated) 文件名,最长256字符 */ }
struct stat结构体保存文件信息,通过stat(),fstat(),lstat()函数返回,这三个函数的区别是:stat()传入文件路径得到stat,lstat()当传入的是符号链文件时,得到的是符号链文件的信息而不是符号链指向的文件,fstat()传入的是文件描述符而不是文件路径。
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 */ };
以下是ls()函数的全部实现,通过opendir()得到DIR*指针,readdir()函数获得指向struct dirent结构的指针,再通过struct stat得到每一个文件的信息。按字母顺序先输出目录文件名,再输出普通文件。
int ls(std::string path,std::string& ret) { DIR* dirp = opendir(path.c_str()); if(!dirp) { return -1; } struct stat st; struct dirent *dir; std::vector<std::string> file_name; std::vector<std::string> dir_name; while((dir = readdir(dirp)) != NULL) { if(strcmp(dir->d_name,".") == 0 || strcmp(dir->d_name,"..") == 0) { continue; } std::string full_path = path + dir->d_name; if(lstat(full_path.c_str(),&st) == -1) { continue; } std::string name = dir->d_name; //replace the blank char in name with "%$". while(name.find(" ") != std::string::npos) { name.replace(name.find(" "),1,"$%"); } if(S_ISDIR(st.st_mode)) //S_ISDIR()宏判断是否是目录文件 { name += "[d]"; dir_name.push_back(name); } else { file_name.push_back(name); } } closedir(dirp); sort(file_name.begin(),file_name.end()); sort(dir_name.begin(),dir_name.end()); std::stringstream ss_ret; int count = 0; for(auto i=dir_name.begin();i!=dir_name.end();i++) { ss_ret<<*i; count++; if(count%5 == 0) { ss_ret<<std::endl; } else { ss_ret<<" "; } } for(auto i=file_name.begin();i!=file_name.end();i++) { ss_ret<<*i; count++; if(count%5 == 0) //每五个名字回车。 { ss_ret<<std::endl; } else { ss_ret<<" "; } } ret = ss_ret.str(); return 0; }
时间: 2024-10-13 17:46:57