본문 바로가기
개발/C, C++

C++ - 폴더, 파일 관리 함수 정리 with sys/stat.h, dirent.h, fstream

by 피로물든딸기 2023. 9. 9.
반응형

C, C++ 전체 링크

 

참고

- Window Visual Studio에서 폴더의 모든 파일 통합하기

 

- 폴더, 파일 확인 함수
- 지정한 경로의 폴더와 파일을 가져오는 함수
- 지정한 경로의 모든 폴더와 파일을 가져오는 함수 (recursive)
- 파일 존재 여부 확인
- 파일 확장자 확인
- 파일 create, read, update
- 파일 delete
- 폴더 생성
- 하위 폴더 포함하여 모든 폴더 만들기 (recursive, mkdir -p 옵션)
- 폴더 삭제 (빈 폴더인 경우, rmdir)
- 폴더 삭제 (하위 폴더, 파일 모두 포함, rm -r)

 

테스트는 replit에서 가능하다.


폴더, 파일 확인 함수

#include <iostream>
#include <string>
#include <sys/stat.h>

using namespace std;

bool isDirectory(const string& path)
{
	struct stat dirStat;

	if (stat(path.c_str(), &dirStat) != 0)
	{
		cout << path << " 경로 정보 알 수 없음" << endl;
		return false;
	}

	return S_ISDIR(dirStat.st_mode);
}

bool isFile(const string& path)
{
	struct stat fileStat;
	if (stat(path.c_str(), &fileStat) != 0)
	{
		cout << path << " 경로 정보 알 수 없음" << endl;
		return false;
	}

	return S_ISREG(fileStat.st_mode);
}

/*
bool isFile(const string& path) {
  return !isDirectory(path);
}
*/

int main()
{
	string path1 = "./test/contents";
	string path2 = "./test/contents/cartoon.txt";
	string path3 = "./test/contents/empty.txt";

	cout << path1 << " is Directory ? " << isDirectory(path1) << endl;
	cout << path2 << " is Directory ? " << isDirectory(path2) << endl;
	cout << path3 << " is Directory ? " << isDirectory(path3) << endl;

	cout << path1 << " is File ? " << isFile(path1) << endl;
	cout << path2 << " is File ? " << isFile(path2) << endl;
	cout << path3 << " is File ? " << isFile(path3) << endl;

	return 0;
}


지정한 경로의 폴더와 파일을 가져오는 함수

#include <iostream>
#include <string>
#include <vector>

#include <dirent.h>
#include <sys/stat.h>

using namespace std;

#define FILE (1)
#define DIRECTORY (2)

bool isDirectory(const string& path)
{
	struct stat dirStat;

	if (stat(path.c_str(), &dirStat) != 0)
	{
		cout << path << " 경로 정보 알 수 없음" << endl;
		return false;
	}

	return S_ISDIR(dirStat.st_mode);
}

bool isFile(const string& path)
{
	struct stat fileStat;
	if (stat(path.c_str(), &fileStat) != 0)
	{
		cout << path << " 경로 정보 알 수 없음" << endl;
		return false;
	}

	return S_ISREG(fileStat.st_mode);
}

/*
bool isFile(const string& path) {
  return !isDirectory(path);
}
*/

vector<string> getDirectoryContents(const string& dirPath, int option = 0)
{
	vector<string> list;
	DIR* dir = opendir(dirPath.c_str());

	if (dir)
	{
		struct dirent* entry;
		while ((entry = readdir(dir)))
		{
			string name = entry->d_name;

			// 현재 폴더와 상위 폴더는 무시
			if (name == "." || name == "..") continue;
            
			if (option == FILE && isDirectory(dirPath + "/" + name)) continue;
			if (option == DIRECTORY && isFile(dirPath + "/" + name)) continue;

			list.push_back(name);
		}

		closedir(dir);
	}
	else
		cerr << "폴더 열기 실패" << endl;

	return list;
}

int main()
{
	string path = "./test";

	vector<string> allList = getDirectoryContents(path);
	vector<string> fileList = getDirectoryContents(path, FILE);
	vector<string> dirList = getDirectoryContents(path, DIRECTORY);

	if (!allList.empty())
	{
		cout << "파일 및 폴더 목록" << endl;
		for (const string& entry : allList) cout << entry << endl;
	}
	cout << endl;

	if (!fileList.empty())
	{
		cout << "파일 목록" << endl;
		for (const string& entry : fileList) cout << entry << endl;
	}
	cout << endl;

	if (!dirList.empty())
	{
		cout << "폴더 목록" << endl;
		for (const string& entry : dirList) cout << entry << endl;
	}
	cout << endl;

	return 0;
}


지정한 경로의 모든 폴더와 파일을 가져오는 함수 (recursive)

#include <iostream>
#include <string>
#include <vector>

#include <dirent.h>
#include <sys/stat.h>

using namespace std;

#define FILE (1)
#define DIRECTORY (2)

bool isDirectory(const string& path)
{
	struct stat dirStat;

	if (stat(path.c_str(), &dirStat) != 0)
	{
		cout << path << " 경로 정보 알 수 없음" << endl;
		return false;
	}

	return S_ISDIR(dirStat.st_mode);
}

bool isFile(const string& path)
{
	struct stat fileStat;
	if (stat(path.c_str(), &fileStat) != 0)
	{
		cout << path << " 경로 정보 알 수 없음" << endl;
		return false;
	}

	return S_ISREG(fileStat.st_mode);
}

/*
bool isFile(const string& path) {
  return !isDirectory(path);
}
*/

void getDirectoryContentsAll(const string& path, vector<string>& fileList, int option = 0)
{
	DIR* dir = opendir(path.c_str());

	if (dir)
	{
		struct dirent* entry;

		while ((entry = readdir(dir)))
		{
			string name = entry->d_name;

			// 현재 폴더와 상위 폴더는 무시
			if (name == "." || name == "..") continue;

			string fullPath = path + "/" + name;

			if ((option == 0)
				|| (option == FILE && isFile(fullPath))
				|| (option == DIRECTORY && isDirectory(fullPath))) fileList.push_back(fullPath);

			// 폴더는 다시 재귀호출
			if (isDirectory(fullPath)) getDirectoryContentsAll(fullPath, fileList, option);
		}

		closedir(dir);
	}
	else
		cerr << "폴더 열기 실패" << endl;
}

int main()
{
	string path = "./test";

	vector<string> allList, fileList, dirList;

	getDirectoryContentsAll(path, allList);
	getDirectoryContentsAll(path, fileList, FILE);
	getDirectoryContentsAll(path, dirList, DIRECTORY);

	if (!allList.empty())
	{
		cout << "파일 및 폴더 목록" << endl;
		for (const string& entry : allList) cout << entry << endl;
	}
	cout << endl;

	if (!fileList.empty())
	{
		cout << "파일 목록" << endl;
		for (const string& entry : fileList) cout << entry << endl;
	}
	cout << endl;

	if (!dirList.empty())
	{
		cout << "폴더 목록" << endl;
		for (const string& entry : dirList) cout << entry << endl;
	}
	cout << endl;

	return 0;
}


파일 존재 여부 확인

#include <iostream>
#include <string>

#include <fstream>

using namespace std;

bool fileExists(const string &filename)
{
	ifstream file(filename);
	return file.good();
}

int main()
{
	string path = "./test/library/github.js";

	if (fileExists(path))
		cout << "파일 찾기 성공" << endl;
	else
		cerr << "파일 찾기 실패" << endl;

	return 0;
}

파일 확장자 확인

#include <iostream>
#include <string>

#include <fstream>

using namespace std;

bool isFileExtension(const string &filename, const string &extension)
{
	size_t dotPosition = filename.rfind('.');
	if (dotPosition == string::npos) return false;

	string fileExtension = filename.substr(dotPosition + 1);

	return fileExtension == extension;
}

int main()
{
	string path = "./test/library/github.js";

	if (isFileExtension(path, "js"))
		cout << "확장자 일치" << endl;
	else
		cerr << "확장자 불일치" << endl;

	return 0;
}

파일 create, read, update

 

create의 경우 폴더가 존재해야 한다.

#include <iostream>
#include <string>

#include <fstream>

using namespace std;

bool fileCreate(const string &fileName, const string &contents)
{
	ofstream file(fileName);
	if (file.is_open())
	{
		file << contents;
		file.close();

		return true;
	}

	return false;
}

bool fileRead(const string &filename)
{
	ifstream file(filename);

	if (!file.is_open())
	{
		cerr << "파일 열기 실패" << endl;
		return false;
	}

	string line;
	while (getline(file, line)) cout << line << endl;

	file.close();
	return true;
}

int main()
{
	string path = "./test/newFile.txt";

	if (fileCreate(path, "hello world!"))
		cout << "파일 생성 성공" << endl;
	else
		cerr << "파일 생성 실패" << endl;

	if (fileRead(path))
		cout << "파일 읽기 성공" << endl;
	else
		cerr << "파일 읽기 실패" << endl;

	if (fileCreate(path, "file change!!"))
		cout << "파일 변경 성공" << endl;
	else
		cerr << "파일 변경 실패" << endl;

	if (fileRead(path))
		cout << "파일 읽기 성공" << endl;
	else
		cerr << "파일 읽기 실패" << endl;

	return 0;
}


파일 delete

#include <iostream>
#include <string>

using namespace std;

int fileDelete(const char *path) 
{ 
	return remove(path); 
}

int fileDelete(const string& path) 
{ 
	return remove(path.c_str()); 
}

int main()
{
	string path = "./test/file.txt";

	if (fileDelete(path) == 0)
		cout << "파일 삭제 성공" << endl;
	else
		cerr << "파일 삭제 실패" << endl;

	return 0;
}

폴더 생성

 

S_IRWXU (User): 사용자(파일 소유자)에 대한 읽기, 쓰기 및 실행 권한
- S_IRUSR (User Read): 읽기 권한 (4)
- S_IWUSR (User Write): 쓰기 권한 (2)
- S_IXUSR (User Execute): 실행 권한 (1)


S_IRWXG (Group): 그룹에 대한 읽기, 쓰기 및 실행 권한
- S_IRGRP (Group Read): 읽기 권한 (4)
- S_IWGRP (Group Write): 쓰기 권한 (2)
- S_IXGRP (Group Execute): 실행 권한 (1)


S_IROTH (Others): 기타 사용자(그룹 및 사용자가 아닌 다른 모든 사용자)에 대한 읽기 권한
S_IXOTH (Others): 기타 사용자(그룹 및 사용자가 아닌 다른 모든 사용자)에 대한 실행 권한

#include <iostream>
#include <string>
#include <sys/stat.h>

using namespace std;

int makeDirectory(const string& path)
{
	return mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
}

int main()
{
	string path = "./newPath/test/test";

	if (makeDirectory(path) == 0)
		cout << "폴더 생성 성공" << endl;
	else
		cerr << "폴더 생성 실패" << endl;

	return 0;
}

 

하위 폴더 포함하여 모든 폴더 만들기 (recursive, mkdir -p 옵션)

#include <iostream>
#include <string>
#include <sys/stat.h>
#include <cstring> // for strerror
//#include <cerrno>  // for errno

using namespace std;

bool makeDirectory(const string& path)
{
	if (mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0) return true;

	// 이미 폴더가 존재하는 경우
	if (errno == EEXIST) return true;

	// 중간 폴더가 없는 경우, 경로의 모든 중간 폴더 생성
	if (errno == ENOENT)
	{
		const size_t last_slash_idx = path.find_last_of('/');
		if (last_slash_idx != string::npos)
		{
			const string parent_dir = path.substr(0, last_slash_idx);
			if (!makeDirectory(parent_dir)) return false; // 중간 폴더 생성 실패
		}

		// 중간 폴더 생성 후, 폴더 생성 재시도
		if (mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0) return true;

		return false; // 폴더 생성 실패
	}

	cout << "error number : " << errno << endl;
	return false; // 다른 오류로 인한 폴더 생성 실패
}

int main()
{
	string directoryPath = "./path1/path2/path3/path4/path5";

	if (makeDirectory(directoryPath))
		cout << "폴더 생성 성공" << endl;
	else
		cerr << "폴더 생성 실패 : " << strerror(errno) << std::endl;

	return 0;
}


폴더 삭제 (빈 폴더인 경우, rmdir)

#include <iostream>
#include <string>
#include <cstdlib>

using namespace std;

int deleteDirectory(const string& path)
{
	string command = "rmdir " + path;
	return system(command.c_str());
}

int main()
{
	string path = "./path1";

	if (deleteDirectory(path) == 0)
		cout << "폴더 삭제 성공" << endl;
	else
		cerr << "폴더 삭제 실패" << endl;

	return 0;
}

 

폴더 삭제 (하위 폴더, 파일 모두 포함, rm -r)

#include <iostream>
#include <string>
#include <cstdlib>

using namespace std;

int deleteDirectory(const string& path)
{
	string command = "rm -r " + path;
	return system(command.c_str());
}

int main()
{
	string path = "./path1";

	if (deleteDirectory(path) == 0)
		cout << "폴더 삭제 성공" << endl;
	else
		cerr << "폴더 삭제 실패" << endl;

	return 0;
}
반응형

댓글