meideru blog

家電メーカーで働いているmeideruのブログです。主に技術系・ガジェット系の話を書いています。

【Windows API】C言語でディレクトリ内を全て走査するプログラム

      2019/05/12

ちょっとわけあって、ディレクトリ内を走査するプログラムを書く必要がありました。

ネットなども駆使して色々と調べてみましたが、サンプルプログラムが見つかりませんでした(^_^;)

なので、自分で書いてみました(´・ω・`)

C言語でディレクトリ内を全て走査して表示するプログラムを作ってみました。ディレクトリ内の子ディレクトリのファイルも全て表示できます。

後でソースコードの解説は詳しくしますが、以下のプログラムではWin32 API を使っているので、Unix系では実行出来ません(´;ω;`)

ソースコード

// 引数として渡したディレクトリ以下のディレクトリとファイルを全て表示する

#define _CRT_SECURE_NO_WARNINGS

#include <Windows.h>
#include <stdio.h>
#include <locale.h>

void PrintDirsAndFiles(const wchar_t* dirpath);

int main(void)
{
	// Unicodeのロケールを全範囲で日本語に設定
	setlocale(LC_ALL, "japanese");

	// 表示する
	PrintDirsAndFiles(L"C:\\");

	return 0;
}


// 引数として渡したディレクトリ以下のディレクトリとファイルを全て表示する
void PrintDirsAndFiles(const wchar_t* dirpath)
{
	HANDLE hFind;				// ハンドル
	WIN32_FIND_DATA win32fd;	// ファイル情報

	// ディレクトリにワイルドカードを追加(...\\*となる)
	wchar_t dirwildpath[1024];		// ファイル名も含んだパス
	wcscpy(dirwildpath, dirpath);	// ファイルパスをコピー
	wcscat(dirwildpath, L"*");		// ワイルドカードを追加

	// ハンドルを取得しファイル情報を保存する
	hFind = FindFirstFile(dirwildpath, &win32fd);

	// 何も見つからなかったとき
	if (hFind == INVALID_HANDLE_VALUE) {
		FindClose(hFind);
		return;
	}

	do {
		// カレントディレクトリと親ディレクトリのとき
		if ((wcscmp(win32fd.cFileName, L".") == 0)
			|| (wcscmp(win32fd.cFileName, L"..") == 0)) {
			// 何もしない
		} else if (win32fd.dwFileAttributes // ディレクトリのときの処理 
			& FILE_ATTRIBUTE_DIRECTORY) {

			// ディレクトリ名を表示
			wprintf(L"(DIR)-%ls\n", win32fd.cFileName);

			// 文字列バッファを更新
			wchar_t dir_buf[1024];
			wcscpy(dir_buf, dirpath);	// ディレクトリをコピーする
			wcscat(dir_buf, win32fd.cFileName);
			wcscat(dir_buf, L"\\");

			// 再帰する
			PrintDirsAndFiles(dir_buf);
		} else { // ファイルのとき
			// ファイル名を表示
			wprintf(L"(FILE)-%ls\n", win32fd.cFileName);
		}

	} while (FindNextFile(hFind, &win32fd));

	FindClose(hFind);
}

このプログラムは、Cドライブ以下のディレクトリとファイルを全て表示します。

ソースコードを書き換えることによって、表示するディレクトリを変更できます。

使い方

表示するディレクトリを変更したいときは、18行目のパスを変更してください。

例えば、デスクトップ上のディレクトリとファイルを表示したいならば

(例)PrintDirsAndFiles(L“C:\\Users\\(ユーザーの名前)\\Desktop\\”);

みたいな感じで変更してください。

ソースコードの解説

Win32 API を使用しています

#include <windows.h>でわかるように、Win32 API を使用しています。

いろいろ調べて分かったことは、ディレクトリを走査するにはAPIを使用しなければならないようです。なので、Windowsでしか利用出来ません。

重要なのはFindFirstFileとFindNextFile関数

FindFirstFileで、任意のディレクトリ内のディレクトリまたはファイルを取得します。

FineNextFileは、FineFirstFileで取得したハンドルを引数として渡すと、任意のディレクトリ内の次のディレクトリまたはファイルを取得することができます。

これら2つの関数の詳しい使い方については、MSDNを参考にしてください(^o^)

再帰を使っている

再帰とは関数が自分で自分のことをもう一度呼び出すことです。本プログラムでは再帰を用いています。

具体的には、ディレクトリを見つけたときに、そのディレクトリ内を探すために、ディレクトリを引数として渡して再帰しています。

因みに、私は再帰をあまり使ったことがないです^^; オセロのプログラムを作るときにミニマックス法を実現するために書いた程度です^^;

カレントディレクトリと親ディレクトリの発見に注意する

ディレクトリ内を走査していくと、「.」と「..」というディレクトリを発見することがあります。これは、それぞれカレントディレクトリと親ディレクトリのことです。

この2つのディレクトリ内は、探索しないようにしなくてはなりません。そのために、49行目で「何もしない」としています。

ワイド文字を使用している

FindFirstFileとFindNextFileの引数は全てワイド文字で表現されるようなので、最初からワイド文字前提でプログラムを書きました。

マルチバイト文字とワイド文字については、複雑で奥が深いので、いつか個別で記事を書きたいですね(^o^)

 

以上です。

何か間違いなどがありましたら、是非とも教えて下さい\(^o^)/

 

ノシ

 - 技術系