windows 递归文件搜索

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/978644/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 12:37:18  来源:igfitidea点击:

recursive file search

c++windowswinapirecursion

提问by Charles Khunt

I'm trying to figure out how to work this thing out .. For some reason, it ends at a certain point.. I'm not very good at recursion and I'm sure the problem lies somewhere there..

我正试图弄清楚如何解决这个问题..出于某种原因,它在某个点结束..我不太擅长递归,我确定问题出在那里..

Also, even if I checked for cFileName != "..", it still shows up at the end, not sure why but the "." doesn't show up anymore..

另外,即使我检查了 cFileName != "..",它仍然显示在最后,不知道为什么,但是 "." 不再出现。。

void find_files( wstring wrkdir )
{
    wstring temp;

    temp = wrkdir + L"\" + L"*"; 
    fHandle = FindFirstFile( temp.c_str(), &file_data );

    if( fHandle == INVALID_HANDLE_VALUE )
    {
         return;
    }
    else 
    { 
        while( FindNextFile( fHandle, &file_data ) ) 
        {
            if( file_data.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY &&
                wcscmp(file_data.cFileName, L".") != 0 && 
                        wcscmp(file_data.cFileName, L"..") != 0 )
            {
                find_files( wrkdir + L"\" + file_data.cFileName  );
            }
            else if( file_data.dwFileAttributes != FILE_ATTRIBUTE_HIDDEN && 
                 file_data.dwFileAttributes != FILE_ATTRIBUTE_SYSTEM  )
            {
                results << wrkdir << "\" << file_data.cFileName << endl;
            }
        }
    }
}

After changing those, the program doesn't enumerate the remaining files left..

更改这些后,程序不会枚举剩余的文件。

For example, if there is a sub folder named test, it enumerates everything inside test but doesn't finish enumerating the files inside the original directory specified.

例如,如果有一个名为 test 的子文件夹,它会枚举 test 中的所有内容,但不会枚举指定原始目录中的文件。

采纳答案by Brian R. Bondy

From the FindFirstFiledocumentation:

FindFirstFile文档:

If the function fails or fails to locate files from the search string in the lpFileName parameter, the return value is INVALID_HANDLE_VALUE and the contents of lpFindFileData are indeterminate.

如果函数失败或无法从 lpFileName 参数中的搜索字符串中定位文件,则返回值为 INVALID_HANDLE_VALUE 并且 lpFindFileData 的内容不确定。

You should only exit from the one iteration not the whole program:

您应该只退出一次迭代而不是整个程序:

   if( fHandle == INVALID_HANDLE_VALUE )
   {
     return;
   }

And this may solve your other problem:

这可能会解决您的其他问题:

else if( file_data.dwFileAttributes != FILE_ATTRIBUTE_HIDDEN && 
   file_data.dwFileAttributes != FILE_ATTRIBUTE_SYSTEM  &&
   wcscmp(file_data.cFileName, L".") != 0 && 
   wcscmp(file_data.cFileName, L"..") != 0
 )
{
    results << wrkdir << "\" << file_data.cFileName << endl;
}

Also see @fretje's answer as well. It gives another problem that your code has.

另请参阅@fretje 的回答。它给您的代码带来了另一个问题。

Updated new:You need to use fHandle as a local variable as well, not global variable.

更新内容:您还需要将 fHandle 用作局部变量,而不是全局变量。

Change to:

改成:

 HANDLE fHandle = FindFirstFile( temp.c_str(), &file_data );

回答by fretje

You are changing the value of your local wrkdirvariable:

您正在更改局部wrkdir变量的值:

wrkdir = wrkdir + L"\" + file_data.cFileName;
find_files( wrkdir );

I think you have to call find_filesthere like this:

我认为你必须find_files像这样打电话:

find_files( wrkdir + L"\" + file_data.cFileName );

and not change the value of wrkdir.

并且不改变 的值wrkdir

回答by Remy Lebeau

There are still several bugs in your code. Try this instead:

您的代码中仍然存在一些错误。试试这个:

void find_files( wstring wrkdir )
{
    wstring wrkdirtemp = wrkdir;
    if( !wrkdirtemp.empty() && (wrkdirtemp[wrkdirtemp.length()-1] != L'\')  )
    {
      wrkdirtemp += L"\";
    }

    WIN32_FIND_DATA file_data = {0};
    HANDLE hFile = FindFirstFile( (wrkdirtemp + L"*").c_str(), &file_data );

    if( hFile == INVALID_HANDLE_VALUE )
    {
         return;
    }

    do
    {
        if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
        {
            if( (wcscmp(file_data.cFileName, L".") != 0) && 
                (wcscmp(file_data.cFileName, L"..") != 0) )
            {
                find_files( wrkdirtemp + file_data.cFileName );
            }
        }
        else
        {
            if( (file_data.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) == 0 )
            {
                results << wrkdirtemp << file_data.cFileName << endl;
            }
        }
    }
    while( FindNextFile( hFile, &file_data );

    FindClose( hFile );
}

回答by Alexander Ponomarev

Recursive file search with dirent.h

使用 dirent.h 进行递归文件搜索

#include <iostream>
#include <dirent.h>
#include <string.h>    

bool isUpDirecory(const char* directory) {
        if (strcmp(directory, "..") == 0 || strcmp(directory, ".") == 0)
            return true;
        else
            return false;
    }

    bool findFile(const std::string& fileName, const std::string& path,
            std::string& resultPath) {
        dirent* entry;
        DIR* dir = opendir(path.c_str());

        if (dir == NULL)
            return false;

        while ((entry = readdir(dir)) != NULL) {
            if (entry->d_type == DT_REG) {
                if (fileName.compare(entry->d_name) == 0) {
                    resultPath = path + "/" + entry->d_name;
                    closedir(dir);
                    return true;
                }
            }
        }

        rewinddir(dir);

        while ((entry = readdir(dir)) != NULL) {
            if (entry->d_type == DT_DIR) {
                if (!isUpDirecory(entry->d_name)) {
                    std::string nextDirectoryPath = path + "/" + entry->d_name;
                    bool result = findFile(fileName, nextDirectoryPath, resultPath);
                    if (result == true) {
                        closedir(dir);
                        return true;
                    }
                }
            }
        }

        closedir(dir);
        return false;
    }

    int main() {
        std::string path;
        bool result = findFile("text.txt", "/home/lamerman/", path);
        std::cout << path << std::endl;
        return 0;
    }

回答by sean e

Also, check out the implementation of the CFileFind MFCclass.

此外,请查看CFileFind MFC类的实现。

回答by Andrey

You still have errors in your code:

您的代码中仍然存在错误:

  1. you ignore the results of the first search. you call FindFirstFile and handle if it fails. But if it succeeds you do not process already fetched file_data and overwrite it with FindNextFile.
  2. You don't close the search handle. Use FindClose for that.
  3. From your existing code it seems that fHandle is global - it shouldn't. It would break your recursion.
  1. 你忽略了第一次搜索的结果。你调用 FindFirstFile 并处理它是否失败。但是如果它成功了,你就不会处理已经获取的 file_data 并用 FindNextFile 覆盖它。
  2. 您没有关闭搜索句柄。为此使用 FindClose。
  3. 从您现有的代码看来, fHandle 是全球性的 - 它不应该。它会破坏你的递归。

Also I think that you can resolve all the issues in your code by paying more attention to MSDN sample provided in FindFirstFile documentation.

此外,我认为您可以通过更多地关注 FindFirstFile 文档中提供的 MSDN 示例来解决代码中的所有问题。