C#を使って、指定したフォルダの配下にある全てのファイルについて、ファイル名、ファイルサイズ、タイムスタンプを取り出す方法について解説します。
本記事の応用として「【ソース公開】指定したフォルダ配下のファイル名や日付を取得するコマンドを作ってみた」という記事も公開しています。こちらはコマンドとして作成しており、ソースコード一式もダウンロードできるようにしていますので、興味のある方は併せてご覧下さい。
フォルダ配下にある全ファイルを取り出すには
DirectoryInfoクラスにある GetFiles メソッド、もしくは EnumerateFiles メソッドを使うことで、指定したフォルダ配下の全ファイルの情報を取得することが可能です。
このクラスは名前空間 System.IO にあるので、ソースコードの冒頭で using System.IO を記述しておきます。
両者の違いは、戻り値が FileInfo[] か IEnumerable<FileInfo> の違いです。
もう少し詳しく説明すると、GetFiles は全てのファイル検索が終了した時点で、その結果をまとめて配列で返してくるのに対し、EnumerableFiles は検索にヒットしたファイルをその都度返してくれます。
もしファイル取得の途中でキーボードにり中断したい場合や、例外発生時に処理を行いたい場合は、EnuerableFiles を使う必要があります。
それでは、詳しく見ていきましょう。
GetFilesによるファイル情報の取得
GetFilesを使うには、あらかじめ DirectoryInfo の引数に対象となるフォルダを指定して、インスタンスを生成しておく必要があります。
DirectoryInfo info = new DirectoryInfo(検索対象のパス);
例えば、Dドライブ直下を指定する場合は次のように記述します。
DirectoryInfo info = new DirectoryInfo(@"d:\);
この例では info というインスタンスを生成していますが、この info にある GetFiles メソッドを呼び出します。
GetFileの第1引数で指定する serchPattern は、ファイルを検索する際の検索パターンであり、"*.txt" や "data0??.csv" などの様にワイルドカードが使用できます。
第2引数は検索範囲を指定するためのもので、SearchOption.TopDirectoryOnly を指定するとトップディレクトリのみ、SearchOption.AllDirectoriesを指定すると配下にある全てのディレクトリが対象となります。
GetFiles(string searchPattern, SearchOption searchOption)
以下は path で指定したフォルダ配下にある全てのファイルの情報を配列として返す関数のサンプルです。
public FileInfo[] Files(string path)
{
return new DirectoryInfo(path).GetFiles("*", SearchOption.TopDirectoryOnly);
}
このサンプルでは、DirectoriInfo のインスタンス生成と GetFiles の呼び出しを1行で行っています。
また、第1引数の searchPattern に "*" を記述していますので、すべてのファイルが対象となります。
EnumerateFilesによるファイル情報の取得
EnumerableFilesを使う場合も、GetFilesと同様、あらかじめ DirectoryInfo の引数に対象となるフォルダを指定して、インスタンスを生成しておきます。
EnumerateFiles(string searchPattern, SearchOption searchOption)
引数は GetFiles と全く同じであり、第1引数には検索パターン、第2引数には検索範囲を指定します。
以下は path で指定したフォルダ配下にある全てのファイルの情報を配列として返す関数のサンプルですが、GetFiles の部分が EnuerateFiles に代わっている以外は全く同じです。
public IEnumerable<FileInfo> Files(string path)
{
return new DirectoryInfo(path).EnumerateFiles("*", SearchOption.AllDirectories);
}
ちなみに、この関数を使って取得したファイル情報を一括して配列に入れたい場合は、必ず ToArray() を末尾に付加することを忘れないでください。
でないと、いつまでたっても配列に結果が格納されません。
Files(path).ToArray();
アクセス権の無いフォルダでもエラーを発生させない方法
指定したフォルダの中にアクセス権が無いフォルダが含まれていた場合、その時点でエラーになり処理が止まってしまいます。
自分が作成したフォルダ配下で自分自身のアクセス権が無いという事態は極めて稀ですが、フォルダを指定せずドライブだけを指定した場合、ほぼ確実にエラーが発生してファイル情報が取得できません。
下記はGetFiles で Dドライブ直下( @"d:\") を指定した場合のエラーです。
各ドライブのルートには、RECYCLE.BIN というゴミ箱用の隠しフォルダが作られていて、通常はこのフォルダへのアクセス権はありません。
この対策をするには EnumerableFiles を使ってファイル情報を1つづつ取り出し、アクセス権の無いフォルダに対してはエラーを握りつぶすという方法が一番簡単です。
以下のサンプルは、引数で指定されたフォルダ名(ディレクトリ名)直下のファイル情報を取得した後に、SearchOption.AllDirectories が指定されていた場合は直下のフォルダに対してもファイル情報を取得するようにしたものです。
また、IEnumerable<FileInfo> で逐次結果を返していますので、EnumerableFiles と同じように扱うことが可能です。
このままコピー&ペーストして頂ければすぐに使えます。
/// <summary>
/// ファイル情報の一覧を取得する。
/// アクセス権限が無いディレクトリは無視する(例外を発生させない)。
/// </summary>
/// <param name="directory"></param>
/// <param name="filter"></param>
/// <param name="searchOption"></param>
/// <returns></returns>
static public IEnumerable<FileInfo> Files(string directory, string filter, SearchOption searchOption = SearchOption.AllDirectories)
{
List<FileInfo> infos = new List<FileInfo>();
//ディレクトリが未指定ならカレントディレクトリを対象とする。
directory = (directory.Trim() == "") ? System.IO.Directory.GetCurrentDirectory() : directory;
//指定されたディレクトリの情報を取得
DirectoryInfo dir_top = new DirectoryInfo(directory);
try
{
//指定されたディレクトリ直下に存在するファイル情報を取得
foreach (var info in dir_top.EnumerateFiles(filter))
{
infos.Add(info);
}
}
catch { }
//取得したファイル情報を返す
foreach (var info in infos)
{
yield return info;
}
//サーチオプションが配下のディレクトリを検索対象にしている場合
if (searchOption == SearchOption.AllDirectories)
{
//指定されたディレクトリ直下にあるディレクトリを全て取得
foreach (var dir_info in dir_top.EnumerateDirectories("*"))
{
infos.Clear();
try
{
//取得したディレクトリ直下から末端までの階層をたぐって全てのファイル情報を取得
foreach (var info in dir_info.EnumerateFiles(filter, SearchOption.AllDirectories))
{
infos.Add(info);
}
}
catch { }
//取得したファイル情報を返す
foreach (var info in infos)
{
yield return info;
}
}
}
}
FileInfo からファイル情報を取り出すには
今までの方法でフォルダ配下のファイル情報を取り出すことができました。
次は、このファイル情報(FileInfo)から必要な値を取り出す方法を説明します。
FileInfo には様々なメソッドやプロパティが用意されていますので、詳しく知りたい方は こちら の記事をご覧ください。
ここでは、一般的によく使うであろうプロパティのみを記載致します。
型 | プロパティ名 | 内容 |
---|---|---|
string | FullName | ファイルのフルパス(絶対パス) |
string | DirectoryName | ディレクトリ名 |
string | Name | ファイル名 |
string | Extention | 拡張子(.txt,.csvなど) |
long | Length | ファイルサイズ(バイト) |
DateTime | CreationTime | 作成日時 |
DateTime | LastWriteTime | 更新日時 |
DateTime | LastAccessTime | アクセス日時 |
以下は、path で指定したフォルダに対して、DirectoryInfo の EnuerateFiles を使ってすべてのファイル情報を取得し、ファイル名のフルパス、ファイルサイズ、作成日時、更新日時、アクセス日時をカンマ区切りでコンソール出力する例です。
var di = new DirectoryInfo(path);
foreach (var file in di.EnumerateFiles("*", SearchOption.AllDirectories))
{
//ファイル情報から必要な情報を取り出す
List<string> column = new List<string>();
column.Add(file.FileName);
column.Add(file.Length.ToString();
column.Add(file.CreationTime.ToString("yyyy/MM/dd HH:mm:ss"));
column.Add(file.LastWriteTime.ToString("yyyy/MM/dd HH:mm:ss"));
column.Add(file.LastAccessTime.ToString("yyyy/MM/dd HH:mm:ss"));
//コンソールにファイル情報を出力
Console.WriteLine(string.Join(",",column));
}
まとめ
今回は指定したフォルダに対して、その配下にある全てのファイル情報の取得と、ファイル情報からファイル名やファイルサイズ、ファイルスタンプを取得する方法を解説致しました。
また、検索フォルダにドライブのみを指定した場合、ゴミ箱用の隠しフォルダをアクセスした時点でアクセス権無しのエラーが発生するため、これを回避するサンプルプログラムについても解説致しました。
コピぺして使えるように関数化していますので、是非ご活用下さい。