如何获取给定文件夹中具有特定扩展名的文件列表?

Posted

技术标签:

【中文标题】如何获取给定文件夹中具有特定扩展名的文件列表?【英文标题】:How to get list of files with a specific extension in a given folder? 【发布时间】:2012-06-23 19:47:51 【问题描述】:

我想获取给定文件夹(以及其子文件夹)中具有特定扩展名的所有文件的文件名。也就是说,文件名(和扩展名),而不是完整的文件路径。这在 Python 等语言中非常简单,但我不熟悉 C++ 中的构造。怎么办?

【问题讨论】:

boost::filesystem 擅长处理文件。 在 Python 之后编写 C++ 一定感觉就像在 C++ 之后用汇编语言编写一样 :) 就标准 C++ 而言,这是一项令人惊讶的代码密集型任务。我赞同使用boost::filesystem 的建议。 【参考方案1】:
#define BOOST_FILESYSTEM_VERSION 3
#define BOOST_FILESYSTEM_NO_DEPRECATED 
#include <boost/filesystem.hpp>

namespace fs = boost::filesystem;

/**
 * \brief   Return the filenames of all files that have the specified extension
 *          in the specified directory and all subdirectories.
 */
std::vector<fs::path> get_all(fs::path const & root, std::string const & ext)

    std::vector<fs::path> paths;

    if (fs::exists(root) && fs::is_directory(root))
    
        for (auto const & entry : fs::recursive_directory_iterator(root))
        
            if (fs::is_regular_file(entry) && entry.path().extension() == ext)
                paths.emplace_back(entry.path().filename());
        
    

    return paths;
             

【讨论】:

那里,这是便携式答案。 唯一对我不起作用的是'and',我用'&&'代替了它。其余的都很棒。 +1 注意:对于扩展不要忘记添加一个点...例如“.jpg”是正确的,而不是“jpg”。 代码是using namespace std;(应该加上) 另请注意,此代码仅提供文件名(即没有文件的完整路径)。如果您需要完整路径,请删除 .filename() 调用。否则,此代码效果很好。谢谢!【参考方案2】:

C++17 代码

#include <fstream>
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;

int main()

    std::string path("/your/dir/");
    std::string ext(".sample");
    for (auto &p : fs::recursive_directory_iterator(path))
    
        if (p.path().extension() == ext)
            std::cout << p.path().stem().string() << '\n';
    
    return 0;

【讨论】:

由于 C++17 已经推出 2 年了,我认为您可以从包含和命名空间中删除 experimental :) 我很惊讶这低于其他非跨平台、非 STL 解决方案!唯一可以进行的其他改进是使用 std::endl 或将 'p' 设置为 const 变量。 @RaleighL。 std::endl 是一种危险的悲观主义,因为它处于一个循环中。 \n 默认更正确【参考方案3】:

在 Windows 上你可以这样做:

void listFiles( const char* path )

   struct _finddata_t dirFile;
   long hFile;

   if (( hFile = _findfirst( path, &dirFile )) != -1 )
   
      do
      
         if ( !strcmp( dirFile.name, "."   )) continue;
         if ( !strcmp( dirFile.name, ".."  )) continue;
         if ( gIgnoreHidden )
         
            if ( dirFile.attrib & _A_HIDDEN ) continue;
            if ( dirFile.name[0] == '.' ) continue;
         

         // dirFile.name is the name of the file. Do whatever string comparison 
         // you want here. Something like:
         if ( strstr( dirFile.name, ".txt" ))
            printf( "found a .txt file: %s", dirFile.name );

       while ( _findnext( hFile, &dirFile ) == 0 );
      _findclose( hFile );
   

在 Posix 上,如 Linux 或 OsX:

void listFiles( const char* path )

   DIR* dirFile = opendir( path );
   if ( dirFile ) 
   
      struct dirent* hFile;
      errno = 0;
      while (( hFile = readdir( dirFile )) != NULL ) 
      
         if ( !strcmp( hFile->d_name, "."  )) continue;
         if ( !strcmp( hFile->d_name, ".." )) continue;

         // in linux hidden files all start with '.'
         if ( gIgnoreHidden && ( hFile->d_name[0] == '.' )) continue;

         // dirFile.name is the name of the file. Do whatever string comparison 
         // you want here. Something like:
         if ( strstr( hFile->d_name, ".txt" ))
            printf( "found an .txt file: %s", hFile->d_name );
       
      closedir( dirFile );
   

【讨论】:

您的解决方案会在模式“foo.txt.exe”中找到文件。我不认为有 .txt 扩展名。 在windows上,你在哪里设置“gIgnoreHidden”的值。是一面旗帜吗? 是的 - 在示例中它是一个全局布尔值。但实际上你可以在这里做任何事情——比如将它作为另一个参数传递给 listFiles。 在从 Windows 8 (?) 开始的 x64 版本上,我相信 hFile 应该是 intptr_t 而不是 long。调用 _findnext 时使用 long 会导致错误。【参考方案4】:

获取文件列表并处理每个文件并遍历它们并存储回不同的文件夹

void getFilesList(string filePath,string extension, vector<string> & returnFileName)

    WIN32_FIND_DATA fileInfo;
    HANDLE hFind;   
    string  fullPath = filePath + extension;
    hFind = FindFirstFile(fullPath.c_str(), &fileInfo);
    if (hFind != INVALID_HANDLE_VALUE)
        returnFileName.push_back(filePath+fileInfo.cFileName);
        while (FindNextFile(hFind, &fileInfo) != 0)
            returnFileName.push_back(filePath+fileInfo.cFileName);
        
    

使用:您可以像这样使用从文件夹中加载所有文件并逐个循环播放

String optfileName ="";        
String inputFolderPath =""; 
String extension = "*.jpg*";
getFilesList(inputFolderPath,extension,filesPaths);
vector<string>::const_iterator it = filesPaths.begin();
while( it != filesPaths.end())

    frame = imread(*it);//read file names
        //doyourwork here ( frame );
    sprintf(buf, "%s/Out/%d.jpg", optfileName.c_str(),it->c_str());
    imwrite(buf,frame);   
    it++;

【讨论】:

【参考方案5】:

您没有说您使用的是什么操作系统,但有多种选择。

正如评论者所说,如果您可以使用 boost,boost::filesystem 将起作用。

其他选项是

CFileFind Class with MFC FindFirstFile/FindNextFile with WIN32 opendir/readdir with POSIX。

【讨论】:

【参考方案6】:

这是我的解决方案(适用于 *nix 系统):

#include <dirent.h>

bool FindAllFiles(std::string path, std::string type, std::vector<std::string> &FileList)
  DIR *dir;
  struct dirent *ent;
  FileList.clear();

  if ((dir = opendir (path.c_str())) != NULL) 
    //Examine all files in this directory
    while ((ent = readdir (dir)) != NULL) 
      std::string filename = std::string(ent->d_name);
      if(filename.length() > 4)
        std::string ext = filename.substr(filename.size() - 3);
        if(ext == type)
          //store this file if it's correct type
          FileList.push_back(filename);
        
      
    
    closedir (dir);
   else 
    //Couldn't open dir
    std::cerr << "Could not open directory: " << path << "\n";
    return false;
  
  return true;

显然将所需的扩展名更改为您喜欢的任何内容。也假定为 3 个字符类型。

【讨论】:

以上是关于如何获取给定文件夹中具有特定扩展名的文件列表?的主要内容,如果未能解决你的问题,请参考以下文章

如何从数组中查找具有特定扩展名的文件列表

在 Objective-C 中的指定路径获取具有特定扩展名的文件列表

搜索包含列表中的单词并具有特定文件扩展名的文件名

在文件夹中查找具有特定扩展名的文件

如何在perl中验证具有给定文件扩展名的多个文件

搜索具有特定扩展名的文件并将其放入列表中