读目录

读目录

头文件<dirent.h>相关函数介绍

对某个目录具有访问权限的任何用户都可以读目录

但是,为了防止文件系统产生混乱,只有内核才能写目录

一个目录的写权限位和执行权限位决定了在该目录中能否创建新文件以及删除文件,并不是能否写目录本身

UNIX现在包含了一套与目录有关的程序,它们是POSIX.1的一部分。很多实现阻止应用程序使用read函数去读取目录的内容,由此进一步将应用程序与目录中实现相关的细节隔离。

  1. #include <dirent.h>
  2. DIR *opendir(const char *pathname);
  3. DIR *fdopendir(int fd);
  4. Both return: pointer if OK, NULL on error
  5. struct dirent *readdir(DIR *dp);
  6. Returns: pointer if OK, NULL at end of directory or error
  7. void rewinddir(DIR *dp);
  8. int closedir(DIR *dp);
  9. Returns: 0 if OK, ?1 on error
  10. long telldir(DIR *dp);
  11. Returns: current location in directory associated with dp
  12. void seekdir(DIR *dp, long loc);

图1 <dirent.h>文件里的函数原型

  telldirseekdir函数不是基本POSIX.1标准组成部分,是Single UNIX Specification中的XSI扩展

定义在<dirent.h>头文件中的dirent结构与实现有关,实现此结构体的定义至少包含下列两个成员:

ino_t d_ino;                  /* i-node number */
char  d_name[];           /* null-terminated filename */

注意,d_name项的大小没有指定,但必须保证它能包含至少NAME_MAX个字节(不包含终止null字节)

DIR结构是一个内部结构,上述7个函数用这个内部结构保存当前正在被读的目录的有关信息

opendirfdopendir返回的指向DIR结构的指针由另外5个函数使用

opendir执行初始化操作,使第一个readdir返回目录中的第一个目录项

注意,目录中各个目录项的顺序与实现有关,它们通常并不按字母顺序排序

实例

编写一个遍历文件层次结构的程序,并统计各种类型文件的数量

  1. /**
  2. * 文件内容: 编写一个遍历文件层次结构的程序,并统计各种类型文件的数量
  3. * 文件时间: 2016年 11月 13日 星期日 15:30:31 CST
  4. * 作者: [email protected]
  5. */
  6. #include <stdio.h>
  7. #include <sys/types.h>
  8. #include <sys/stat.h>
  9. #include <unistd.h>
  10. #include <dirent.h>
  11. #include <string.h>
  12. #include <stdarg.h> // ISO C variable aruments
  13. #include <stdlib.h>
  14. #include <errno.h>
  15. #define MAXLINE 4096 // max line length
  16. // function type that is called for each filename
  17. typedef int MyFunc(const char *, const struct stat *, int);
  18. static MyFunc g_myFunc;
  19. static char *g_fullPath;
  20. static size_t g_pathLen;
  21. static long g_nTotal = 0L;
  22. static long g_nReg = 0L;
  23. static long g_nDir = 0L;
  24. static long g_nBlk = 0L;
  25. static long g_nChr = 0L;
  26. static long g_nFifo = 0L;
  27. static long g_nSlink = 0L;
  28. static long g_nSock = 0L;
  29. #define FTW_F 1 /* file other than directory */
  30. #define FTW_D 2 /* directory */
  31. #define FTW_DNR 3 /* directory that can‘t be read */
  32. #define FTW_NS 4 /* file that we can‘t stat */
  33. static void err_doit(int, int, const char *, va_list);
  34. static int myFtw(char *, MyFunc *);
  35. static int doPath(MyFunc *myFunc);
  36. /**
  37. * Print a message and return to caller.
  38. * Caller specifies "errnoflag".
  39. */
  40. static void err_doit(int errnoflag, int error, const char *fmt, va_list ap)
  41. {
  42. char buf[MAXLINE] = { 0 };
  43. vsnprintf(buf, MAXLINE - 1, fmt, ap);
  44. if (errnoflag)
  45. {
  46. snprintf(buf+strlen(buf), MAXLINE-strlen(buf)-1, ": %s",
  47. strerror(error));
  48. }
  49. strcat(buf, "\n");
  50. fflush(stdout); /* in case stdout and stderr are the same */
  51. fputs(buf, stderr);
  52. fflush(NULL); /* flushes all stdio output streams */
  53. }
  54. /**
  55. * Fatal error unrelated to a system call.
  56. * Print a message and terminate.
  57. */
  58. static void err_quit(const char *fmt, ...)
  59. {
  60. va_list ap;
  61. va_start(ap, fmt);
  62. err_doit(0, 0, fmt, ap);
  63. va_end(ap);
  64. exit(1);
  65. }
  66. /**
  67. * Nonfatal error related to a system call.
  68. * Print a message and return.
  69. */
  70. static void err_ret(const char *fmt, ...)
  71. {
  72. va_list ap;
  73. va_start(ap, fmt);
  74. err_doit(1, errno, fmt, ap);
  75. va_end(ap);
  76. }
  77. /**
  78. * Fatal error related to a system call.
  79. * Print a message and terminate.
  80. */
  81. static void err_sys(const char *fmt, ...)
  82. {
  83. va_list ap;
  84. va_start(ap, fmt);
  85. err_doit(1, errno, fmt, ap);
  86. va_end(ap);
  87. exit(1);
  88. }
  89. /**
  90. * Fatal error related to a system call.
  91. * Print a message, dump core, and terminate.
  92. */
  93. static void err_dump(const char *fmt, ...)
  94. {
  95. va_list ap;
  96. va_start(ap, fmt);
  97. err_doit(1, errno, fmt, ap);
  98. va_end(ap);
  99. abort(); /* dump core and terminate */
  100. exit(1); /* shouldn‘t get here */
  101. }
  102. int main(int argc, char ** argv)
  103. {
  104. int ret = 0;
  105. if (argc != 2)
  106. {
  107. err_quit("usage: ftw <starting-pathname>");
  108. }
  109. ret = myFtw(argv[1], g_myFunc);
  110. g_nTotal = g_nReg + g_nDir + g_nBlk + g_nChr + g_nFifo + g_nSlink + g_nSock;
  111. if (0 == g_nTotal)
  112. {
  113. g_nTotal = 1L;
  114. }
  115. printf("regular files = %7ld, %5.2f %%\n", g_nReg, g_nReg * 100.0 / g_nTotal);
  116. printf("directories = %7ld, %5.2f %%\n", g_nDir, g_nDir * 100.0 / g_nTotal);
  117. printf("block special = %7ld, %5.2f %%\n", g_nBlk, g_nBlk * 100.0 / g_nTotal);
  118. printf("char special = %7ld, %5.2f %%\n", g_nChr, g_nChr * 100.0 / g_nTotal);
  119. printf("FIFOS = %7ld, %5.2f %%\n", g_nFifo, g_nFifo * 100.0 / g_nTotal);
  120. printf("symbolic links = %7ld, %5.2f %%\n", g_nSlink, g_nSlink * 100.0 / g_nTotal);
  121. printf("sockets = %7ld, %5.2f %%\n", g_nSock, g_nSock * 100.0 / g_nTotal);
  122. // remember free
  123. if (g_fullPath != NULL)
  124. {
  125. free(g_fullPath);
  126. g_fullPath = NULL;
  127. }
  128. exit(ret);
  129. }
  130. static long g_posix_version = 0L;
  131. static long g_xsi_version = 0L;
  132. #ifdef PATH_MAX
  133. static long g_pathMax = PATH_MAX;
  134. #else
  135. static long g_pathMax = 0;
  136. #endif
  137. /* If PATH_MAX is indeterminate, no guarantee this is adequate */
  138. #define PATH_MAX_GUESS 1024
  139. char *path_alloc(size_t *sizep)
  140. {
  141. char *ptr = NULL;
  142. size_t size = 0;
  143. if (g_posix_version == 0)
  144. {
  145. g_posix_version = sysconf(_SC_VERSION);
  146. }
  147. if (g_xsi_version == 0)
  148. {
  149. g_xsi_version = sysconf(_SC_XOPEN_VERSION);
  150. }
  151. if (g_pathMax == 0)
  152. {
  153. /* first time through */
  154. errno = 0;
  155. if ((g_pathMax = pathconf("/", _PC_PATH_MAX)) < 0)
  156. {
  157. if (errno == 0)
  158. {
  159. g_pathMax = PATH_MAX_GUESS; /* it‘s indeterminate */
  160. }
  161. else
  162. {
  163. err_sys("pathconf error for _PC_PATH_MAX");
  164. }
  165. }
  166. else
  167. {
  168. g_pathMax++; /* add one since it‘s relative to root */
  169. }
  170. }
  171. /*
  172. * Before POSIX.1-2001, we aren‘t guaranteed that PATH_MAX includes
  173. * the terminating null byte. Same goes for XPG3.
  174. */
  175. if ((g_posix_version < 200112L) && (g_xsi_version < 4))
  176. {
  177. size = g_pathMax + 1;
  178. }
  179. else
  180. {
  181. size = g_pathMax;
  182. }
  183. if ((ptr = malloc(size)) == NULL)
  184. {
  185. err_sys("malloc error for pathname");
  186. }
  187. if ((ptr = memset(ptr, 0, size)) == NULL)
  188. {
  189. err_sys("memset error for pathname");
  190. }
  191. if (sizep != NULL)
  192. {
  193. *sizep = size;
  194. }
  195. return(ptr);
  196. }
  197. static int myFtw(char *pathName, MyFunc *myFunc)
  198. {
  199. g_fullPath = path_alloc(&g_pathLen);
  200. if (g_pathLen < strlen(pathName))
  201. {
  202. g_pathLen = strlen(pathName) * 2;
  203. if (realloc(g_fullPath, g_pathLen) == NULL)
  204. {
  205. err_sys("realloc failed");
  206. }
  207. }
  208. strcpy(g_fullPath, pathName);
  209. return doPath(myFunc);
  210. }
  211. /**
  212. * we return whatever myFunc return
  213. */
  214. static int doPath(MyFunc *myFunc)
  215. {
  216. struct stat statBuf;
  217. if (lstat(g_fullPath, &statBuf) < 0) // stat error
  218. {
  219. return myFunc(g_fullPath, &statBuf, FTW_NS);
  220. }
  221. if (S_ISDIR(statBuf.st_mode) == 0) // not a diretctory
  222. {
  223. return myFunc(g_fullPath, &statBuf, FTW_F);
  224. }
  225. // It‘s a directory, first call myFunc() for the directory,
  226. // then process each filename in the directory.
  227. int ret = 0;
  228. if (ret = myFunc(g_fullPath, &statBuf, FTW_D) != 0)
  229. {
  230. return ret;
  231. }
  232. int n = strlen(g_fullPath);
  233. if (n + NAME_MAX + 2 > g_pathLen) // expand path buffer
  234. {
  235. g_pathLen *= 2;
  236. if ((g_fullPath = realloc(g_fullPath, g_pathLen)) == NULL)
  237. {
  238. err_sys("realloc failed");
  239. }
  240. }
  241. g_fullPath[n++] = ‘/‘;
  242. g_fullPath[n] = ‘\0‘;
  243. DIR *dp = NULL;
  244. if ((dp = opendir(g_fullPath)) == NULL) // can‘t read directory
  245. {
  246. return myFunc(g_fullPath, &statBuf, FTW_DNR);
  247. }
  248. struct dirent *pDir = NULL;
  249. while((pDir = readdir(dp)) != NULL)
  250. {
  251. if (0 == strcmp(".", pDir->d_name) || 0 == strcmp("..", pDir->d_name))
  252. {
  253. continue; // ignore dot and dot-dot
  254. }
  255. strcpy(&(g_fullPath[n]), pDir->d_name); // append name after "/"
  256. if ((ret = doPath(myFunc)) != 0) // recursive
  257. {
  258. break; // time to leave
  259. }
  260. }
  261. g_fullPath[n - 1] = ‘\0‘; // erase everything from slash onward
  262. if (closedir(dp) < 0)
  263. {
  264. err_ret("can‘t close directory %s", g_fullPath);
  265. }
  266. return ret;
  267. }
  268. static int ftw_f(const char *pathName, const struct stat *statPtr, int type)
  269. {
  270. switch(statPtr->st_mode & S_IFMT)
  271. {
  272. case S_IFREG:
  273. g_nReg++;
  274. break;
  275. case S_IFBLK:
  276. g_nBlk++;
  277. break;
  278. case S_IFCHR:
  279. g_nChr++;
  280. break;
  281. case S_IFIFO:
  282. g_nFifo++;
  283. break;
  284. case S_IFLNK:
  285. g_nSlink++;
  286. break;
  287. case S_IFSOCK:
  288. g_nSock++;
  289. break;
  290. case S_IFDIR: // directories should have type = FTW_D
  291. err_dump("for S_IFDIR for %s, directories should have type = FTW_D", pathName);
  292. break;
  293. default:
  294. err_dump("%s unknown type %d for pathname %s", __FUNCTION__, type, pathName);
  295. break;
  296. }
  297. }
  298. static int g_myFunc(const char *pathName, const struct stat *statPtr, int type)
  299. {
  300. switch (type)
  301. {
  302. case FTW_F:
  303. ftw_f(pathName, statPtr, type);
  304. break;
  305. case FTW_D:
  306. g_nDir++;
  307. break;
  308. case FTW_DNR:
  309. err_ret("can‘t read directory %s", pathName);
  310. break;
  311. case FTW_NS:
  312. err_ret("stat error for %s", pathName);
  313. break;
  314. default:
  315. err_dump("%s unknown type %d for pathname %s", __FUNCTION__, type, pathName);
  316. break;
  317. }
  318. return 0;
  319. }

图2. 递归降序遍历目录层次结构,并按文件类型计数

程序运行如下:

$ ./a.out  .
regular files  =       4,     33.33 %
directories    =       6,     50.00 %
block special  =       0,      0.00 %
char special   =       0,      0.00 %
FIFOS          =       0,      0.00 %
symbolic links =       2,     16.67 %
sockets        =       0,      0.00 %

参考

UNIX环境高级编程(第三版)    4.22 读目录

时间: 2024-11-05 14:40:35

读目录的相关文章

windows中java读目录空格变成%20 处理方法

URL url = Thread.currentThread().getContextClassLoader().getResource(""); String path = url.getPath(); System.out.print(path); 打印输出: path = URLDecoder.decode(path, "utf-8"); System.out.print(path); 打印输出: 总结:java读目录空格变成%20 处理方法,使用utf-8字

VC++读目录下所有文件

#include <iostream> #include <io.h> #include <direct.h> #include <string> #include <vector> #include <iomanip> #include <ctime> using namespace std; void getFiles( string, vector<string>& ); int main() {

搜索文件-读目录的使用

#include<stdio.h> #include<sys/stat.h> #include<string.h> #include<errno.h> #include<stdlib.h> #include<dirent.h> void err_sys(const char *s) { printf("%s error:%s\n",s,strerror(errno)); exit(0); } bool isFind

windows下有个目录名称中间有空格 java读目录空格变成%20 处理方法

String path=Parameter.class.getResource("").getPath();//得到路径//String path=Parameter.class.getResource("").toString();//这个不行,无法处理里面的空格.//System.out.println(path); 对路径中的空格取消的话,那么就要对路径进行转码path=URLDecoder.decode(path,"utf-8");//关

apue第四章 文件和目录

函数stat,fstat,fstatat, lstat #include <sys/stat.h> int stat(const char *restrict pathname, struct stat *restrict buf); int fstat(int fd, struct stat *buf); int lstat(const char *restrict pathname, struct stat *restrict buf); int lstat(int fd, const c

C语言中关于对目录的操作

原文地址:C语言中关于对目录的操作 目录的操作不论是在嵌入式产品还是应用软件编程都是必不可少的,不同的开发语言可能略有不同,笔者主要是讨论在Linux平台下对目录的一系列操作: 1.获取当前目录操作: 在系统命令行下我们可以直接输入命令:pwd 来获取当前的工作目录,但是你知道这个命令是怎么执行的吗?它是由系统通过 Shell 程序来解释执行的,在我们自己编写程序的时候怎么能获取当前的工作目录呢?在标准C库中提供了一系列关于目录操作的接口函数: char * getcwd(char * buf,

APUE(4)---文件和目录 (3)

十三.函数rename和renameat #include <stdio.h> int rename(const char *oldname, const char *newname); int renameat(int oldfd, const char *oldname, int newfd, const char *newname); 文件或目录可以用rename函数或者renameat函数进行重命名.有几种情况需要说明: 1.如果oldname指的是一个文件而不是目录,那么为该文件或符

UNIX 环境高级编程 文件和目录

函数stat , fstat , fstatat , lstat stat函数返回与此文件有关的信息结构. fstat函数使用已打开的文件描述符(而stat则使用文件名) fstatat函数 为一个相对于当前打开目录的路径名返回文件信息. lstat函数返回该符号链接的有关信息,而不是该符号链接引用的文件的信息. 使用stat最多的地方可能就是 ls -l 命令. st_mode  与 S_IFMT 进行 与 运算 在与 S_IFXXX常量相比较,来判断类型. 文件类型 1.普通文件: 无论是文

Notes for Apue &mdash;&mdash; chapter 4 Files and Directories(文件和目录)

4.1 Introduction 4.2 stat, fstat, fstatat, and lstat Functions The lstat function is similar to stat, but when the named file is a symbolic link, lstat returns information about the symbolic link, not the file referenced by the symbolic link. 4.3 文件类