如何在C中遍历目录
我在我的应用程序中使用 glib,并且我发现 glib 中有用于 C 的 remove
、unlink
和 rmdir
的便捷包装器。但这些一次只能对单个文件或目录起作用。
据我所知,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);
显然,我会构建一些错误处理等,以便在遇到致命错误时立即中止该过程。
I am using glib in my application, and I see there are convenience wrappers in glib for C's remove
, unlink
and rmdir
. But these only work on a single file or directory at a time.
As far as I can see, neither the C standard nor glib include any sort of recursive directory walk functionality. Nor do I see any specific way to delete an entire directory tree at once, as with rm -rf
.
For what I'm doing this I'm not worried about any complications like permissions, symlinks back up the tree (infinite recursion), or anything that would rule out a very naive
implementation... so I am not averse to writing my own function for it.
However, I'm curious if this functionality is out there somewhere in the standard libraries gtk or glib (or in some other easily reused C library) already and I just haven't stumbled on it. Googling this topic generates a lot of false leads.
Otherwise my plan is to use this type of algorithm:
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);
Obviously I would build in some error handling and the like to abort the process as soon as a fatal error is encountered.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
你看过
吗? AFAIK 这属于 POSIX 规范,它应该是大多数(如果不是全部)C 编译器标准库的一部分。请参阅此
参考(Open Group 的单一 UNIX 规范版本 2)。PS,在有人对此发表评论之前:不,这不提供递归目录遍历。但我认为这最好由开发人员来实现;需求可能有很大差异,因此一刀切的递归遍历函数必须非常强大。 (例如:符号链接是否跟进?递归深度是否应该受到限制?等等)
Have you looked at
<dirent.h>
? AFAIK this belongs to the POSIX specification, which should be part of the standard library of most, if not all C compilers. See e.g. this<dirent.h>
reference (Single UNIX specification Version 2 by the Open Group).P.S., before someone comments on this: No, this does not offer recursive directory traversal. But then I think this is best implemented by the developer; requirements can differ quite a lot, so one-size-fits-all recursive traversal function would have to be very powerful. (E.g.: Are symlinks followed up? Should recursion depth be limited? etc.)
如果你想用 glib 来完成,你可以使用 GFileEnumerator 。
You can use GFileEnumerator if you want to do it with glib.
几个平台包括 ftw 和 nftw:“(新)文件树遍历”。检查 imac 上的手册页表明这些都是旧版,新用户应该更喜欢 fts。可移植性可能是这些选择中的任何一个的问题。
Several platforms include ftw and nftw: "(new) file tree walk". Checking the man page on an imac shows that these are legacy, and new users should prefer fts. Portability may be an issue with either of these choices.
标准 C 库旨在提供原始功能。你所说的是复合行为。您可以使用您选择的 API 中存在的低级功能轻松实现它 - 看看本教程。
Standard C libraries are meant to provide primitive functionality. What you are talking about is composite behavior. You can easily implement it using the low level features present in your API of choice -- take a look at this tutorial.
请注意,您提到的remove()、unlink() 和rmdir() 的“便利包装器”(假设您指的是在中声明的那些)并不是真正的“便利包装器”。在完全标准的函数前面加上“g_”有什么方便? (请注意,即使我首先介绍了它们,我也会这么说。)
这些包装器存在的唯一原因是 Windows 上的文件名问题,其中这些包装器实际上由真实代码组成;它们采用 Unicode 格式的文件名参数,以 UTF-8 编码。相应的“解包”Microsoft C 库函数采用系统代码页中的文件名。
如果您不是专门编写可移植到 Windows 的代码,则没有理由使用 g_remove() 等包装器。
Note that the "convenience wrappers" you mention for remove(), unlink() and rmdir(), assuming you mean the ones declared in <glib/gstdio.h>, are not really "convenience wrappers". What is the convenience in prefixing totally standard functions with a "g_"? (And note that I say this even if I who introduced them in the first place.)
The only reason these wrappers exist is for file name issues on Windows, where these wrappers actually consist of real code; they take file name arguments in Unicode, encoded in UTF-8. The corresponding "unwrapped" Microsoft C library functions take file names in system codepage.
If you aren't specifically writing code intended to be portable to Windows, there is no reason to use the g_remove() etc wrappers.