如何使用 C 或 C++ 获取目录中的文件列表?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/612097/
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
How can I get the list of files in a directory using C or C++?
提问by samoz
How can I determine the list of files in a directory from inside my C or C++ code?
如何从我的 C 或 C++ 代码中确定目录中的文件列表?
I'm not allowed to execute the ls
command and parse the results from within my program.
我不允许ls
在我的程序中执行命令和解析结果。
回答by Peter Parker
In small and simple tasks I do not use boost, I use dirent.hwhich is also available for windows:
在小而简单的任务中,我不使用 boost,我使用dirent.h,它也可用于 Windows:
DIR *dir;
struct dirent *ent;
if ((dir = opendir ("c:\src\")) != NULL) {
/* print all the files and directories within directory */
while ((ent = readdir (dir)) != NULL) {
printf ("%s\n", ent->d_name);
}
closedir (dir);
} else {
/* could not open directory */
perror ("");
return EXIT_FAILURE;
}
It is just a small header file and does most of the simple stuff you need without using a big template-based approach like boost(no offence, I like boost!).
它只是一个小的头文件,可以在不使用像 boost 这样的基于模板的大方法的情况下完成你需要的大部分简单的事情(没有冒犯,我喜欢 boost!)。
The author of the windows compatibility layer is Toni Ronkko. In Unix, it is a standard header.
windows兼容层的作者是Toni Ronkko。在 Unix 中,它是一个标准的头文件。
UPDATE 2017:
2017 年更新:
In C++17 there is now an official way to list files of your file system: std::filesystem
. There is an excellent answer from Shreevardhanbelow with this source code:
在 C++17 中,现在有一种正式的方法来列出文件系统的文件:std::filesystem
. 下面是Shreevardhan 的一个很好的答案,带有这个源代码:
#include <string>
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main()
{
std::string path = "/path/to/directory";
for (const auto & entry : fs::directory_iterator(path))
std::cout << entry.path() << std::endl;
}
回答by Shreevardhan
C++17 now has a std::filesystem::directory_iterator
, which can be used as
C++17 现在有一个std::filesystem::directory_iterator
,可以用作
#include <string>
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main() {
std::string path = "/path/to/directory";
for (const auto & entry : fs::directory_iterator(path))
std::cout << entry.path() << std::endl;
}
Also, std::filesystem::recursive_directory_iterator
can iterate the subdirectories as well.
此外,std::filesystem::recursive_directory_iterator
也可以迭代子目录。
回答by Brian R. Bondy
Unfortunately the C++ standard does not define a standard way of working with files and folders in this way.
不幸的是,C++ 标准没有定义以这种方式处理文件和文件夹的标准方式。
Since there is no cross platform way, the best cross platform way is to use a library such as the boost filesystem module.
由于没有跨平台方式,最好的跨平台方式是使用诸如boost 文件系统模块之类的库。
Cross platform boost method:
跨平台提升方法:
The following function, given a directory path and a file name, recursively searches the directory and its sub-directories for the file name, returning a bool, and if successful, the path to the file that was found.
bool find_file(const path & dir_path, // in this directory, const std::string & file_name, // search for this name, path & path_found) // placing path here if found { if (!exists(dir_path)) return false; directory_iterator end_itr; // default construction yields past-the-end for (directory_iterator itr(dir_path); itr != end_itr; ++itr) { if (is_directory(itr->status())) { if (find_file(itr->path(), file_name, path_found)) return true; } else if (itr->leaf() == file_name) // see below { path_found = itr->path(); return true; } } return false; }
以下函数,给定目录路径和文件名,递归搜索目录及其子目录以查找文件名,返回一个布尔值,如果成功,则返回找到的文件的路径。
bool find_file(const path & dir_path, // in this directory, const std::string & file_name, // search for this name, path & path_found) // placing path here if found { if (!exists(dir_path)) return false; directory_iterator end_itr; // default construction yields past-the-end for (directory_iterator itr(dir_path); itr != end_itr; ++itr) { if (is_directory(itr->status())) { if (find_file(itr->path(), file_name, path_found)) return true; } else if (itr->leaf() == file_name) // see below { path_found = itr->path(); return true; } } return false; }
Source from the boost page mentioned above.
来自上述提升页面的来源。
For Unix/Linux based systems:
对于基于 Unix/Linux 的系统:
You can use opendir/ readdir/ closedir.
您可以使用opendir/ readdir/ closedir。
Sample code which searches a directory for entry ``name'' is:
len = strlen(name); dirp = opendir("."); while ((dp = readdir(dirp)) != NULL) if (dp->d_namlen == len && !strcmp(dp->d_name, name)) { (void)closedir(dirp); return FOUND; } (void)closedir(dirp); return NOT_FOUND;
在目录中搜索条目“name”的示例代码是:
len = strlen(name); dirp = opendir("."); while ((dp = readdir(dirp)) != NULL) if (dp->d_namlen == len && !strcmp(dp->d_name, name)) { (void)closedir(dirp); return FOUND; } (void)closedir(dirp); return NOT_FOUND;
Source code from the above man pages.
来自上述手册页的源代码。
For a windows based systems:
对于基于 Windows 的系统:
You can use the Win32 API FindFirstFile/ FindNextFile/ FindClosefunctions.
您可以使用 Win32 API FindFirstFile/ FindNextFile/ FindClose函数。
The following C++ example shows you a minimal use of FindFirstFile.
#include <windows.h> #include <tchar.h> #include <stdio.h> void _tmain(int argc, TCHAR *argv[]) { WIN32_FIND_DATA FindFileData; HANDLE hFind; if( argc != 2 ) { _tprintf(TEXT("Usage: %s [target_file]\n"), argv[0]); return; } _tprintf (TEXT("Target file is %s\n"), argv[1]); hFind = FindFirstFile(argv[1], &FindFileData); if (hFind == INVALID_HANDLE_VALUE) { printf ("FindFirstFile failed (%d)\n", GetLastError()); return; } else { _tprintf (TEXT("The first file found is %s\n"), FindFileData.cFileName); FindClose(hFind); } }
以下 C++ 示例向您展示了 FindFirstFile 的最小用法。
#include <windows.h> #include <tchar.h> #include <stdio.h> void _tmain(int argc, TCHAR *argv[]) { WIN32_FIND_DATA FindFileData; HANDLE hFind; if( argc != 2 ) { _tprintf(TEXT("Usage: %s [target_file]\n"), argv[0]); return; } _tprintf (TEXT("Target file is %s\n"), argv[1]); hFind = FindFirstFile(argv[1], &FindFileData); if (hFind == INVALID_HANDLE_VALUE) { printf ("FindFirstFile failed (%d)\n", GetLastError()); return; } else { _tprintf (TEXT("The first file found is %s\n"), FindFileData.cFileName); FindClose(hFind); } }
Source code from the above msdn pages.
来自上述 msdn 页面的源代码。
回答by herohuyongtao
One function is enough, you don't need to use any 3rd-party library (for Windows).
一个功能就足够了,您不需要使用任何 3rd 方库(适用于 Windows)。
#include <Windows.h>
vector<string> get_all_files_names_within_folder(string folder)
{
vector<string> names;
string search_path = folder + "/*.*";
WIN32_FIND_DATA fd;
HANDLE hFind = ::FindFirstFile(search_path.c_str(), &fd);
if(hFind != INVALID_HANDLE_VALUE) {
do {
// read all (real) files in current folder
// , delete '!' read other 2 default folder . and ..
if(! (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
names.push_back(fd.cFileName);
}
}while(::FindNextFile(hFind, &fd));
::FindClose(hFind);
}
return names;
}
PS: as mentioned by @Sebastian, you could change *.*
to *.ext
in order to get only the EXT-files (i.e. of a specific type) in that directory.
PS:正如@Sebastian 所提到的,您可以更改*.*
为*.ext
仅获取该目录中的 EXT 文件(即特定类型)。
回答by congusbongus
For a C only solution, please check this out. It only requires an extra header:
对于仅 C 语言的解决方案,请查看此内容。它只需要一个额外的标题:
https://github.com/cxong/tinydir
https://github.com/cxong/tinydir
tinydir_dir dir;
tinydir_open(&dir, "/path/to/dir");
while (dir.has_next)
{
tinydir_file file;
tinydir_readfile(&dir, &file);
printf("%s", file.name);
if (file.is_dir)
{
printf("/");
}
printf("\n");
tinydir_next(&dir);
}
tinydir_close(&dir);
Some advantages over other options:
与其他选项相比的一些优势:
- It's portable - wraps POSIX dirent and Windows FindFirstFile
- It uses
readdir_r
where available, which means it's (usually) threadsafe - Supports Windows UTF-16 via the same
UNICODE
macros - It is C90 so even very ancient compilers can use it
- 它是可移植的 - 包装了 POSIX dirent 和 Windows FindFirstFile
- 它
readdir_r
在可用的地方使用,这意味着它(通常)是线程安全的 - 通过相同的
UNICODE
宏支持 Windows UTF-16 - 它是 C90 所以即使是非常古老的编译器也可以使用它
回答by Chris Redford
I recommend using glob
with this reusable wrapper. It generates a vector<string>
corresponding to file paths that fit the glob pattern:
我建议使用glob
这个可重用的包装器。它生成一个vector<string>
对应于适合 glob 模式的文件路径:
#include <glob.h>
#include <vector>
using std::vector;
vector<string> globVector(const string& pattern){
glob_t glob_result;
glob(pattern.c_str(),GLOB_TILDE,NULL,&glob_result);
vector<string> files;
for(unsigned int i=0;i<glob_result.gl_pathc;++i){
files.push_back(string(glob_result.gl_pathv[i]));
}
globfree(&glob_result);
return files;
}
Which can then be called with a normal system wildcard pattern such as:
然后可以使用正常的系统通配符模式调用,例如:
vector<string> files = globVector("./*");
回答by Meekohi
Why not use glob()
?
为什么不使用glob()
?
#include <glob.h>
glob_t glob_result;
glob("/your_directory/*",GLOB_TILDE,NULL,&glob_result);
for(unsigned int i=0; i<glob_result.gl_pathc; ++i){
cout << glob_result.gl_pathv[i] << endl;
}
回答by Bad
Here is a very simple code in C++11
using boost::filesystem
library to get file names in a directory (excluding folder names):
这是C++11
使用boost::filesystem
库获取目录中的文件名(不包括文件夹名称)的非常简单的代码:
#include <string>
#include <iostream>
#include <boost/filesystem.hpp>
using namespace std;
using namespace boost::filesystem;
int main()
{
path p("D:/AnyFolder");
for (auto i = directory_iterator(p); i != directory_iterator(); i++)
{
if (!is_directory(i->path())) //we eliminate directories
{
cout << i->path().filename().string() << endl;
}
else
continue;
}
}
Output is like:
输出是这样的:
file1.txt
file2.dat
回答by Shrikant
I think, below snippet can be used to list all the files.
我认为,下面的代码片段可用于列出所有文件。
#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>
static void list_dir(const char *path)
{
struct dirent *entry;
DIR *dir = opendir(path);
if (dir == NULL) {
return;
}
while ((entry = readdir(dir)) != NULL) {
printf("%s\n",entry->d_name);
}
closedir(dir);
}
Following is the structure of the struct dirent
以下是struct dirent的结构
struct dirent {
ino_t d_ino; /* inode number */
off_t d_off; /* offset to the next dirent */
unsigned short d_reclen; /* length of this record */
unsigned char d_type; /* type of file */
char d_name[256]; /* filename */
};
回答by Tim
Try boost for x-platform method
尝试提升 x 平台方法
http://www.boost.org/doc/libs/1_38_0/libs/filesystem/doc/index.htm
http://www.boost.org/doc/libs/1_38_0/libs/filesystem/doc/index.htm
or just use your OS specific file stuff.
或者只是使用您的操作系统特定的文件内容。