C++ Builder XE4 > fileIO > linux:find -maxdepth相当の処理をC++ Builderで実装する

```txt:動作環境
C++ Builder XE4
```

### ファイル探索の問題

- 下層にたくさんのフォルダがあるフォルダで、ファイル探索をすると処理が返るまで時間がかかる

これを回避するため、「フォルダ階層数」に上限を設けた探索を検討する。

### 処理概要

- ファイルを探索する
- linuxコマンドfindでの`-maxdepth`相当機能をC++ Builderでのファイル探索で実装
    - https://explainshell.com/explain?cmd=find+-maxdepth

### ファイル、フォルダ構造

ファイル、フォルダ構図のマインドマップ
https://atlas.mindmup.com/yasokada/_181211/index.html

下記は、上記の画像

![2018-12-11_11h43_58.png](https://qiita-image-store.s3.amazonaws.com/0/32870/29bdf874-b013-33cd-b82f-e1ab98869bbb.png)


### フォームデザイン

![2018-12-11_11h46_47.png](https://qiita-image-store.s3.amazonaws.com/0/32870/2b5b27b1-d383-d436-9f40-fb4a91e08c06.png)

### 実装

```Unit1.h
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include "cspin.h"
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE で管理されるコンポーネント
	TMemo *Memo1;
	TLabel *Label1;
	TButton *B_search;
	TEdit *E_depth;
	void __fastcall B_searchClick(TObject *Sender);
private:	// ユーザー宣言
	String __fastcall findFileInDir_maxdepthOf(String baseDir, String filePattern, int maxdepth);
public:		// ユーザー宣言
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
```

```Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include <IOUtils.hpp>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "cspin"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	Memo1->Lines->Clear();
	E_depth->Text = L"1";
}
//---------------------------------------------------------------------------

String __fastcall TForm1::findFileInDir_maxdepthOf(String baseDir, String filePattern, int maxdepth)
{
	// 同じファイルが複数のフォルダにある場合、上位のフォルダのファイルが探索にひっかかる設計
	//

	// 1. ファイルの探索
	TSearchOption filOpt = TSearchOption::soTopDirectoryOnly;
	TStringDynArray fileList = TDirectory::GetFiles(baseDir, filePattern, filOpt);
	if (fileList.Length > 0) {
		return fileList[0];
	}

	if (maxdepth <= 1) {
		return L"";  // not found
	}

	// 2. フォルダの探査
	TStringDynArray dirList;
	TSearchOption dirOpt = TSearchOption::soTopDirectoryOnly;

	dirList = TDirectory::GetDirectories(baseDir, L"*", dirOpt);

	for(int idx=0; idx < dirList.Length; idx++) {
		String res = findFileInDir_maxdepthOf(dirList[idx], filePattern, (maxdepth-1));
		if (res.Length() > 0) {
			return res;
		}
	}

	return L"";  // not found
}
void __fastcall TForm1::B_searchClick(TObject *Sender)
{
	// 実行ファイル.exeがあるフォルダをベースとする
	String baseDir = ExtractFileDir(Application->ExeName);
	String filPtrn = L"*.csv";  // ファイル名パターン
	int depth = E_depth->Text.ToInt();

	String res = findFileInDir_maxdepthOf(baseDir, filPtrn, depth);
	if (res.Length() == 0) {
		res = L"[NOT FOUND]";
	}


	String msg = L"depth=" + IntToStr(depth) + L":" + res;
	Memo1->Lines->Add(msg);
}
//---------------------------------------------------------------------------
```

### 動作例

上記画像の再掲
![2018-12-11_11h43_58.png](https://qiita-image-store.s3.amazonaws.com/0/32870/29bdf874-b013-33cd-b82f-e1ab98869bbb.png)

動作例
![2018-12-11_11h41_46.png](https://qiita-image-store.s3.amazonaws.com/0/32870/d7ba4d6e-4ec7-f4b4-5621-7603d7b37f85.png)

### 備考

- 同じファイルが複数フォルダにある場合、上位フォルダのファイルが探索にひかっかる
- 下層フォルダにあるファイルが探索にひっかかってほしい場合は、探索方法の変更が必要