C 또는 C ++ 코드 내부에서 디렉토리의 파일 목록을 어떻게 확인할 수 있습니까?
ls
명령 을 실행하고 프로그램 내에서 결과를 구문 분석 할 수 없습니다 .
답변
작고 간단한 작업에서 boost를 사용하지 않고 Windows에서도 사용할 수있는 dirent.h 를 사용합니다.
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;
}
그것은 단지 작은 헤더 파일이며 boost와 같은 큰 템플릿 기반 접근 방식을 사용하지 않고도 필요한 대부분의 간단한 작업을 수행합니다.
Windows 호환성 계층의 작성자는 Toni Ronkko입니다. 유닉스에서는 표준 헤더입니다.
2017 업데이트 :
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;
}
답변
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;
}
또한 std::filesystem::recursive_directory_iterator
서브 디렉토리도 반복 할 수 있습니다.
답변
불행히도 C ++ 표준은 이러한 방식으로 파일 및 폴더를 사용하는 표준 방법을 정의하지 않습니다.
크로스 플랫폼 방식이 없으므로 최상의 크로스 플랫폼 방식은 boost 파일 시스템 모듈 과 같은 라이브러리를 사용하는 것 입니다.
크로스 플랫폼 부스트 방법 :
디렉토리 경로 및 파일 이름이 지정된 다음 함수는 디렉토리 및 해당 서브 디렉토리에서 파일 이름을 재귀 적으로 검색하여 부울을 리턴하고 성공하면 발견 된 파일의 경로를 리턴합니다.
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; }
위에서 언급 한 부스트 페이지의 소스.
유닉스 / 리눅스 기반 시스템의 경우 :
opendir / readdir / closedir을 사용할 수 있습니다 .
디렉토리에서“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;
위의 매뉴얼 페이지의 소스 코드.
Windows 기반 시스템의 경우 :
Win32 API FindFirstFile / FindNextFile / FindClose 함수를 사용할 수 있습니다 .
다음 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); } }
위의 msdn 페이지의 소스 코드
답변
하나의 기능만으로도 타사 라이브러리 (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;
}
추신 : @Sebastian에서 언급 한 바와 같이, 당신은 변경 될 수 있습니다 *.*
에 *.ext
해당 디렉토리에만 EXT-파일을 얻기 위해 (즉, 특정 유형의)에서.
답변
C 전용 솔루션의 경우이를 확인하십시오. 추가 헤더 만 필요합니다.
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);
다른 옵션에 비해 몇 가지 장점 :
- 이식성-POSIX dirent 및 Windows FindFirstFile 포장
- 사용
readdir_r
가능한 곳에서 사용 합니다 . 즉, 일반적으로 스레드 안전 - 동일한
UNICODE
매크로 를 통해 Windows UTF-16 지원 - C90이므로 아주 오래된 컴파일러조차도 사용할 수 있습니다.
답변
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;
}
다음과 같은 일반적인 시스템 와일드 카드 패턴으로 호출 할 수 있습니다.
vector<string> files = globVector("./*");
답변
다음은 라이브러리를 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;
}
}
출력은 다음과 같습니다
file1.txt
file2.dat