C++ 使用 Cygwin 递归文件/目录扫描
我正在寻找编写一个便携式文件系统扫描器,能够递归地列出给定目录路径上的所有文件。
为此,我尝试为我的编译器使用 cygwin,利用 dirent.h 并使用模板:
#include <dirent.h>
#include <stdio.h>
int main(void)
{
DIR *d;
struct dirent *dir;
d = opendir(".");
if (d)
{
while ((dir = readdir(d)) != NULL)
{
// Stuff
}
closedir(d);
}
return(0);
}
但还需要添加递归目录搜索。 为此,我的解决方案是尝试在下一个文件上 opendir() ,并判断错误代码以确定它是否已成功作为目录打开(然后我将递归),或者是否返回“不”一个目录',然后它将被列为一个文件。
我承认这感觉很笨拙,但即使经过几个小时的搜索,我也无法找到可以保留一定可移植性的更好方法(不是 win32)。
所以我的简化解决方案(为了简单起见,有些伪代码)看起来像这样:
int scan(string startdir) { DIR *d; struct dirent *dir; d = opendir(startdir.cstr()); if (d) { while ((dir = readdir(d)) != NULL) { if( NOT '.' AND NOT '..') { if(temp = opendir(startdir + d) == NULL) { //FILE OR ERROR }else{ //Opened successfully as a directory, so recurse scan(startdir + d->d_name + "\\"); } } } closedir(d); } return(0); }
这只是半重写的伪代码以保持简单,但它似乎有效(尽管我非常愿意接受有关更好方法的建议)。
然而,我遇到的主要问题是一个特定的链接文件“c:\cygwin\dev\fd”,它似乎作为一个目录打开,并一遍又一遍地递归地无限地打开自身。
“fd”文件大小为 4KB,106 字节,没有扩展名,是一个不指向 Windows 中任何位置的快捷方式。
这个错误似乎表明要么这个 kludgey 方法有问题,要么我正在编译的 cygwin 实现存在问题。
举一个简短的例子:
Error Reading: c:\cygwin\dev\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\0 No such file or directory
排除该目录,搜索似乎运行良好。 但我不同意将排除项硬编码到扫描仪中。
如果有人对此问题有任何想法、建议、解决方案或替代方法,我们将不胜感激。
谢谢。
I'm looking to write a portable filesystem scanner, capable of listing all files on a given directory path recursively.
To do this, I'm attempting to use cygwin for my compiler, making use of dirent.h and using the template:
#include <dirent.h>
#include <stdio.h>
int main(void)
{
DIR *d;
struct dirent *dir;
d = opendir(".");
if (d)
{
while ((dir = readdir(d)) != NULL)
{
// Stuff
}
closedir(d);
}
return(0);
}
But need to add recursive directory searching as well. To do this, my solution was to attempt to opendir() on the next file, and judge the error code to determine if it was successfully opened as a directory (which I would then recurse on) or if it was returned to be 'not a directory', which would then be listed as just a file.
I admit it feels very klugey, but I have been unable to find a better method that can retain some portability (not win32), even after hours of searching.
So my simplified solution (some psuedo for simplicity) is looking something like this:
int scan(string startdir) { DIR *d; struct dirent *dir; d = opendir(startdir.cstr()); if (d) { while ((dir = readdir(d)) != NULL) { if( NOT '.' AND NOT '..') { if(temp = opendir(startdir + d) == NULL) { //FILE OR ERROR }else{ //Opened successfully as a directory, so recurse scan(startdir + d->d_name + "\\"); } } } closedir(d); } return(0); }
This is just half rewritten psuedo code to keep it simple, but it seems to work (although I'm very open to suggestions on better ways to do this).
The major issue I'm having, however, is a particular link file 'c:\cygwin\dev\fd' which seems to be opening as a directory and recursively opening itself over and over infinitely.
The 'fd' file is 4KB, 106 bytes with no extension and is a shortcut that does not point anywhere in Windows.
This error seems to indicate that either this kludgey method is bugged, or there's a problem in the cygwin implementation that I'm compiling in.
As a short example:
Error Reading: c:\cygwin\dev\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\0 No such file or directory
Excluding that directory, the search seems to work well. But I'm not alright with hard coding an exclusion in to the scanner.
If anyone has any ideas, suggestions, solutions, or alternative methods to this problem, your input would be appreciated.
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如果您可以使用 boost,请考虑使用 boost::filesystem 。 这些教程包括一个简单的 ls 程序,您可以轻松扩展该程序以递归方式工作。 该库还包含查询文件类型的方法,这可能可以解决您的特定问题。
If you can use boost, consider using boost::filesystem. The tutorials include a simple ls program that you can easily extend to work recursively. The library also includes methods to query the types of files, which probably can solve your specific problem.
罪魁祸首似乎是 fd 文件链接到 /proc/
我不保证它是真的,但我的印象是这使得扫描仪能够递归地循环遍历它自己的目录结构。
我用 readlink() 来解决这个问题的努力一开始很有希望,但我发现随着扫描的深入,它变得不可靠,并且错误仍然可能发生。
我现在正在研究其他方法来实现此功能(即 boost::filesystem)。
The culprit seems to be that the fd file links into /proc/
I do not guarantee it to be true, but I am under the impression that this enables the scanner to recursively loop through its own directory structure.
My efforts with readlink() to address this issue were promising at first, but I'm finding that with deeper levels of scanning, it becomes unreliable and the errors can still occur.
I am now looking into other ways to achieve this functionality (ie boost::filesystem).
那是一个虚拟文件系统,可能带有符号链接。 Cygwin 支持符号链接,您可能必须考虑这一点。
That is a virtual filesystem, maybe with symlinks. Cygwin supports symlinks, and you might have to factor that in.
您确实意识到 cygwin 拥有所有 UNIX 工具。
查找非常有用。
You do realise that cygwin has all the UNIX tools.
Find is very usefull.
cygwin 库同时具有 ftw() 和 fts(),请使用其中之一。
The cygwin library has both ftw() and fts(), use one of those.
在您的示例中,您尝试再次使用 opendir() 来确定某物是文件还是目录。 您可以通过使用“sys/stat.h”中的 stat() 更直接地执行此操作。 这也应该在 cygwin 中可用。 您可以使用宏 S_ISREG() 和 S_ISDIR() 检查常规文件或目录。 可能是这样的:
请同时查看我向其他人提供的答案 ://stackoverflow.com/questions/67273/how-do-you-iterate-through-every-file-directory-recursively-in-standard-c">问题。
In your example you've tried to use opendir() again to determine whether something is a file or a directory. You can do this more directly by using stat() from "sys/stat.h". This should also be available in cygwin. You can use the macros S_ISREG() and S_ISDIR() to check for regular file or directory. Probably something like this:
Please have also a look at the answer I've provided to the other question.