我正在寻找一个便携式文件系统扫描程序,能够递归地列出给定目录路径上的所有文件。
为此,我尝试将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
排除该目录,搜索似乎运行良好。但是,如果不对扫描仪进行硬编码,我就不行了。
如果有人对此问题有任何想法,建议,解决方案或替代方法,我们将不胜感激。
感谢。
答案 0 :(得分:1)
如果您可以使用提升,请考虑使用boost::filesystem。这些教程包含一个简单的ls程序,您可以轻松地将其扩展为递归工作。该库还包括查询文件类型的方法,这可能可以解决您的具体问题。
答案 1 :(得分:1)
罪魁祸首似乎是fd文件链接到/ proc /
我不保证这是真的,但我的印象是这使得扫描程序能够以递归的方式循环遍历自己的目录结构。
我使用readlink()来解决这个问题的努力最初很有希望,但我发现随着扫描程度的提高,它变得不可靠,错误仍然可能发生。
我现在正在研究实现此功能的其他方法(即boost :: filesystem)。
答案 2 :(得分:0)
这是一个虚拟文件系统,可能带有符号链接。 Cygwin支持符号链接,你可能不得不考虑它。
答案 3 :(得分:0)
你确实意识到cygwin拥有所有UNIX工具。
查找非常有用。
答案 4 :(得分:0)
cygwin库有ftw()和fts(),使用其中之一。
答案 5 :(得分:0)
在您的示例中,您尝试再次使用opendir()来确定某些内容是文件还是目录。您可以使用“sys / stat.h”中的stat()直接执行此操作。这也应该在cygwin中提供。您可以使用宏S_ISREG()和S_ISDIR()来检查常规文件或目录。可能是这样的:
struct stat *buf = new struct stat;
if(!stat(d->d_name, buf))
{
if(S_ISREG(buf->st_mode))
{
std::cout << " File: " << entry->d_name << "\n";
}
if(S_ISDIR(buf->st_mode) &&