如何在C语言中遍历目录

8
我在我的应用程序中使用了glib,并且我发现glib中有方便的包装器来使用C语言的removeunlinkrmdir。但是这些仅适用于单个文件或目录。
据我所知,C标准和glib都没有包括任何递归目录遍历功能。也没有看到任何特定的方法来一次性删除整个目录树,就像rm -rf一样。
对于我的工作,我不担心任何复杂情况,例如权限、符号链接回到树上(无限递归)或任何会排除非常天真实现的东西……因此,我不反对编写自己的函数来实现它。
然而,我很好奇这种功能是否已经存在于标准库gtk或glib(或其他易于重用的C库)中,而我只是还没有找到它。在谷歌上搜索这个话题会产生很多误导。
否则,我的计划是使用这种类型的算法:
dir_walk(char* path, void* callback(char*) {
  if(is_dir(path) && has_entries(path)) {
    entries = get_entries(path);
    for(entry in intries) { dir_walk(entry, callback); }
  }
  else { callback(path) }
}

dir_walk("/home/user/trash", remove);

显然,我会建立一些错误处理机制等来在遇到致命错误时立即中止该过程。


1
从技术上讲,只有 remove() 是 C 标准中的函数,另外两个是 POSIX :) - Matt Joiner
1
除了现有的回答之外,请注意,无论是在 C 语言还是任何其他语言中,一个人都不能简单地“步行进入”到 Mordor 目录。 - Error 454
除了现有的答案,我想指出健壮的代码不应该使用递归。应该使用迭代和栈来代替。 - LRN
5个回答

7
你看过<dirent.h>吗?据我所知,它属于POSIX规范,应该是大多数C编译器标准库的一部分,如果不是全部。例如,请参见这个<dirent.h>参考(由Open Group提供的Single UNIX规范第2版)
顺便说一句,在有人评论之前:不,这并不提供递归目录遍历功能。但是我认为最好由开发人员实现此功能;要求可能有很大的差异,因此一个通用的递归遍历函数必须非常强大。(例如:是否跟踪符号链接?递归深度应该限制在什么程度?等等)。

在Windows中,它是opendir/closedir等函数。或者使用FindFirstFile和FindNextFile函数。 - Ronny Brendel

5

如果你想使用glib来完成这个任务,可以使用GFileEnumerator


GFileEnumerator是递归的吗?我阅读了文档,但没有提到这一点。当然,我可以尝试一下并找出答案... - mlibby

5

有几个平台包括ftw和nftw: "(新)文件树遍历"。在iMac上查看man页面显示这些是过时的,新用户应该优先选择fts。使用任何一种选择可能会存在可移植性问题。


3

标准的C库旨在提供基本功能。您所说的是复合行为。您可以使用API中提供的低级特性轻松实现它 - 请参阅此教程


-1
请注意,您提到的remove()、unlink()和rmdir()的“便利包装器”(假设您指的是中声明的那些)并不是真正的“便利包装器”。在完全标准的函数前加上“g_”有什么方便之处呢?(即使是我第一次引入它们时也要注意这一点。)
这些包装器存在的唯一原因是解决Windows上的文件名问题,其中这些包装器实际上由真正的代码组成;它们使用UTF-8编码的Unicode文件名参数。相应的“未包装”的Microsoft C库函数使用系统代码页中的文件名。
如果您不是专门编写旨在在Windows上移植的代码,则没有理由使用g_remove()等包装器。

2
方便之处在于g_版本处理了您讨论的情况。由于我在许多其他事情上都使用glib和gtk,因此保持一致并使用g_函数是有意义的。不这样做会确保我的代码无法移植。我并不是想暗示g_版本仅仅调用标准库。 - mlibby

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接