Window Visual Studio에서 폴더의 모든 파일 통합하기는 C, C++을 이용하여 하위 파일을 통합하였다.
여기서는 유니티 C#을 활용하여 만들어보자.
C, C++에서 사용된 함수는 C#에서는 아래와 같이 사용된다.
isDirectory - 폴더 / 파일 체크 함수 → C# 불필요
getAllFilePath - 해당 경로를 모두 읽어오는 함수 → C# Directory.GetFiles() / GetDirectories() 제공
deleteDirectoryFiles - 폴더, 파일 삭제 함수 → FileInfo.Delete() 제공
deleteAllDirectoryFiles - 모든 폴더, 파일 삭제 함수
fileCopy - 파일 복사 함수 → File.Copy() 제공
numOfDigits - 자릿수를 세는 함수
padStart - 자릿수의 빈칸을 앞부분부터 특정 문자로 채우는 함수
split - 특정 문자열 기준으로 분해하는 함수 → string.Delete() 제공
getExtension - 파일의 확장자를 얻는 함수 → getLastSplit(string, delimeter)로 변형해서 사용
Ctrl + Shift + N으로 빈 오브젝트를 만든 후, RecursiveFolderMeger.cs를 추가하자.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
public class RecursiveFolderMerger : MonoBehaviour
{
const string PATH = "C:\\Users\\username\\Desktop\\MyFiles";
const string RESULT_PATH = "C:\\Users\\username\\Desktop\\Result";
string getLastSplit(string str, char delimeter)
{
string[] split = str.Split(delimeter);
int length = split.Length;
return split[length - 1];
}
void deleteAllDirectoryFiles(string path)
{
DirectoryInfo di = new DirectoryInfo(path);
if (di.Exists == false) return;
FileInfo[] files = di.GetFiles();
foreach (FileInfo file in files) file.Delete();
DirectoryInfo[] subDirectories = di.GetDirectories();
foreach (DirectoryInfo subDirectory in subDirectories) subDirectory.Delete();
Directory.Delete(path);
}
void makeDirectory(string path)
{
DirectoryInfo di = new DirectoryInfo(path);
if (di.Exists == false) di.Create();
}
int numOfDigits(int number)
{
int ret = 0;
while(number != 0)
{
ret++;
number /= 10;
}
return ret;
}
string padStart(int number, int padSize, char pad)
{
string strNum = number.ToString();
string ret = "";
for (int i = 0; i < padSize - strNum.Length; i++) ret = ret + pad;
return ret + strNum;
}
void Start()
{
deleteAllDirectoryFiles(RESULT_PATH);
makeDirectory(RESULT_PATH);
string[] files = Directory.GetFiles(PATH, "*.*", SearchOption.AllDirectories);
int padSize = numOfDigits(files.Length);
int fileIndex = 0;
foreach(string file in files)
{
Debug.Log(file);
string fileName = getLastSplit(file, '\\');
string destPath = RESULT_PATH + "\\" + fileName;
File.Copy(file, destPath, true);
string changeName = RESULT_PATH + "\\file_" + padStart(fileIndex++, padSize, '0') + "." + getLastSplit(fileName, '.');
File.Move(destPath, changeName);
}
}
}
이제 아래 폴더를 적절한 경로(=PATH)에 놔둔 후 RESULT_PATH에 결과를 확인해보자.
위의 폴더는 아래의 디렉토리와 파일로 이루어져 있다.
MyFiles - Folder1, 2, 3 / a, b, z
Folder1 - a, b, z
Folder1 - Folder1-1 - a, b, z
Folder1 - Folder1-2 - a, b, c
Folder2 - a, b, c
Folder3 - a, b
게임을 실행하면 아래의 결과를 얻는다.
하지만 위의 결과는 C, C++에서 파일을 합친 것과 다른 결과를 가진다.
각 파일에 recursive할 때와 C# 순서에 의한 번호를 저장해뒀으니 검증할 때 참고하자.
C, C++에서는 파일이 아래의 순서대로 결합된다.
MyFiles - Folder1, 2, 3 / a(00), b(01), z(02)
Folder1 - a(03), b(04), z(05)
Folder1 - Folder1-1 - a(06), b(07), z(08)
Folder1 - Folder1-2 - a(09), b(10), c(11)
Folder2 - a(12), b(13), c(14)
Folder3 - a(15), b(16)
즉, recursive하게 파일을 먼저 찾고, 해당 폴더로 들어간 후, 파일을 찾고, 다시 폴더를 찾는다.
하지만 C#을 이용해서 합친 결과는 아래와 같다.
MyFiles - Folder1, 2, 3 / a(00), b(01), z(02)
Folder1 - a(03), b(04), z(05)
Folder1 - Folder1-1 - a(06 → 11), b(07 → 12), z(08 → 13)
Folder1 - Folder1-2 - a(09 → 14), b(10 → 15), c(11 → 16)
Folder2 - a(12 → 06), b(13 → 07), c(14 → 08)
Folder3 - a(15 → 09), b(16 → 10)
아래의 코드를 보자.
string[] files = Directory.GetFiles(PATH, "*.*", SearchOption.AllDirectories);
C#에서 제공하는 Directory.GetDirectories에 옵션으로
SearchOption.AllDirectories를 주면 하위 파일을 모두 찾는다.
하지만 문제는 recursive하게 찾지 않고, 같은 깊이의 폴더에 대해 먼저 찾는다.
즉, 첫 번째 깊이의 폴더 Folder1 - Folder2 - Folder3를 찾고,
두 번째 깊이의 폴더 Folder1-1 , Folder1-2를 탐색한다. (너비 우선 탐색)
C#의 방식이 마음에 든다면 여기서 끝내면 된다.
하지만 C, C++ 방식으로 하고 싶다면 직접 recursive하게 file을 구하도록 getRecursiveFiles를 구현해야 한다.
Directory.GetDirectories(path)로 주어진 경로에 있는 디렉토리의 목록을 구할 수 있다.
따라서 아래와 같이 함수를 만들 수 있다.
List<string> files = new List<string>();
void getRecursiveFiles(string path, string extension)
{
// 해당 경로의 파일을 먼저 찾는다.
string[] f = Directory.GetFiles(path, extension);
files.AddRange(f);
// 폴더가 있다면
string[] paths = Directory.GetDirectories(path);
// 각 폴더에 파일을 찾는다.
foreach(string p in paths) getRecursiveFiles(p, extension);
}
files는 전역으로 변경하고 List<string> 타입으로 수정하였다.
그리고 Directory.GetDirectories에 아무 옵션도 주지 않으면 해당 폴더의 파일만 찾는다.
Start에서 실행은 아래와 같이 수정하면 된다.
void Start()
{
deleteAllDirectoryFiles(RESULT_PATH);
makeDirectory(RESULT_PATH);
//string[] files = Directory.GetFiles(PATH, "*.*", SearchOption.AllDirectories);
files = new List<string>();
getRecursiveFiles(PATH, "*.*");
int padSize = numOfDigits(files.Count);
추가로 bool recursive 변수를 줘서 원하는 방식대로 파일을 합칠 수 있도록 수정하였다.
최종 코드는 아래와 같다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
public class RecursiveFolderMerger : MonoBehaviour
{
const string PATH = "C:\\Users\\username\\Desktop\\MyFiles";
const string RESULT_PATH = "C:\\Users\\username\\Desktop\\Result";
public bool recursive;
List<string> files = new List<string>();
string getLastSplit(string str, char delimeter)
{
string[] split = str.Split(delimeter);
int length = split.Length;
return split[length - 1];
}
void deleteAllDirectoryFiles(string path)
{
DirectoryInfo di = new DirectoryInfo(path);
if (di.Exists == false) return;
FileInfo[] files = di.GetFiles();
foreach (FileInfo file in files) file.Delete();
DirectoryInfo[] subDirectories = di.GetDirectories();
foreach (DirectoryInfo subDirectory in subDirectories) subDirectory.Delete();
Directory.Delete(path);
}
void makeDirectory(string path)
{
DirectoryInfo di = new DirectoryInfo(path);
if (di.Exists == false) di.Create();
}
int numOfDigits(int number)
{
int ret = 0;
while(number != 0)
{
ret++;
number /= 10;
}
return ret;
}
string padStart(int number, int padSize, char pad)
{
string strNum = number.ToString();
string ret = "";
for (int i = 0; i < padSize - strNum.Length; i++) ret = ret + pad;
return ret + strNum;
}
void getRecursiveFiles(string path, string extension)
{
// 해당 경로의 파일을 먼저 찾는다.
string[] f = Directory.GetFiles(path, extension);
files.AddRange(f);
// 폴더가 있다면
string[] paths = Directory.GetDirectories(path);
// 각 폴더에 파일을 찾는다.
foreach(string p in paths) getRecursiveFiles(p, extension);
}
void Start()
{
deleteAllDirectoryFiles(RESULT_PATH);
makeDirectory(RESULT_PATH);
if(recursive)
{
files = new List<string>();
getRecursiveFiles(PATH, "*.*");
}
else
{
string[] strfiles = Directory.GetFiles(PATH, "*.*", SearchOption.AllDirectories);
files.AddRange(strfiles);
}
int padSize = numOfDigits(files.Count /* <- files.Length */);
int fileIndex = 0;
foreach(string file in files)
{
Debug.Log(file);
string fileName = getLastSplit(file, '\\');
string destPath = RESULT_PATH + "\\" + fileName;
File.Copy(file, destPath, true);
string changeName = RESULT_PATH + "\\file_" + padStart(fileIndex++, padSize, '0') + "." + getLastSplit(fileName, '.');
File.Move(destPath, changeName);
}
}
}
Unity Plus:
Unity Pro:
Unity 프리미엄 학습:
'개발 > Unity' 카테고리의 다른 글
유니티 - 네비메쉬 에이전트의 경로를 라인 렌더러로 표시하기 (Draw the Path of NavMesh with LineRender) (0) | 2022.08.25 |
---|---|
유니티 - 네비메쉬 에이전트로 장애물 피하면서 이동하기 (0) | 2022.08.25 |
유니티 - 윈도우 빌드 해상도, 창모드 설정하기 (0) | 2022.08.24 |
유니티 UI - PlayerPrefs로 드롭다운 목록 관리하기 (Control TextMeshPro Dropdown with PlayerPrefs) (0) | 2022.08.10 |
유니티 - logMessageReceived로 로그 콜백 추가하기 (0) | 2022.08.09 |
댓글