ファイルの検索

Win32 APIを使用してファイルを検索する方法です。

FindFirstFile,FindNextFile,FindCloseというAPIを使用します。
ディレクトリの場合は検索関数を再帰的に読み込むことで階層を掘り下げて検索をします。

見つかったファイルがディレクトリかどうかの判定のとき少しだけ注意が必要です。 サンプルの中でディレクトリの判定を
if((FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) > 0){
と、しているようにしないと圧縮フォルダなど他の属性が付加されたディレクトリを 判定できなくなります。(単純に等価判定をすると失敗します。)
これも以前はまりましたよ。_| ̄|○
では、サンプルです。

#include <stdio.h>
#include <windows.h>

bool SearchFile(char *start_path,char *search_file,int num,char *result_path,int result_size);
bool ToLower(char *string);

int main()
{
char path[MAX_PATH+1];

path[0] = '\0';
SearchFile("c:\\winnt","rundll32.exe",10,path,MAX_PATH);

printf("result:%s\n",path);

return 0;
}

/////////////////////////////////////////////////////////////////////////////
//指定されたファイルを指定したフォルダ内全部から再帰的に探す
// char *start_path; //最後に\\をつけないように
// char *search_file; //検索対象のファイルorディレクトリ名
// char num; //何階層目まで再帰的に呼び出すか
// char *result_path; //結果を入れる
// char result_size; //結果を入れる領域のサイズ
//見つかると、result_pathにフルパスがコピーされる
bool SearchFile(char *start_path,char *search_file,int num,char *result_path,int result_size)
{
HANDLE Find;
WIN32_FIND_DATA FindData;
char path[MAX_PATH+1];
bool ret = false;

if(start_path == NULL || search_file == NULL || num < 1 || result_path == NULL || result_size < 1){
return false;
}

//最初のファイル?ディレクトリ?
strcpy(path,start_path);
strcat(path,"\\*");
Find = FindFirstFile(path,&FindData);
if(Find == INVALID_HANDLE_VALUE){
return false;
}

do{
//探しているファイル名と一致するか?
ToLower(FindData.cFileName);
if(strcmp(FindData.cFileName,search_file) == 0){
//見つかった!!
strcpy(result_path,start_path);
strcat(result_path,"\\");
strcat(result_path,FindData.cFileName);
ret = true;
break;
}
//ディレクトリの判定して再起呼び出しをする
if((FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) > 0){
//"."と".."は、除外する
if(strcmp(FindData.cFileName,".") != 0 && strcmp(FindData.cFileName,"..") != 0){
strcpy(path,start_path);
strcat(path,"\\");
strcat(path,FindData.cFileName);
if(SearchFile(path,search_file,num-1,result_path,result_size)){
//下の階層で見つかったので終了
ret = true;
break;
}
}
}

//デバッグ出力
//strcpy(path,start_path);
//strcat(path,"\\");
//strcat(path,FindData.cFileName);
//printf("Disagreement:%s\n",path);
}while(FindNextFile(Find,&FindData));

FindClose(Find);

return ret;
}


///////////////////////////////////////////////////////////////////////////
// 文字列をすべて小文字にする
//  引数のデータを書き換えるので注意
bool ToLower(char *string)
{
int len;

if(string == NULL){
return false;
}

len = strlen(string);
for(int i=0 ; i < len ; i++){
*string = (char )tolower(*string);
string++;
}

return true;
}

多分ヘッダは足りてると思います。
このサンプルはびみょーに欠陥があって同じファイル名のものが存在すると 意図どおりの結果になるか分からない点です。
別の言い方だと同名ファイルを複数見つけたい場合には改造が必要です。