DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

ある文字列を含むすべてのファイルを検索する

指定したフォルダ以下にあるファイルのうち、指定した文字列を含むファイルを探す方法を紹介します。

.NET Framework 2.0以降で、My.Computer.FileSystem.FindInFilesメソッドを使用する方法

.NET Framework 2.0以降のVB.NETでは、My.Computer.FileSystem.FindInFilesメソッドにより、可能です。ただし、ファイルの文字コードはEncoding.Default(あるいは、StreamReaderクラスが判別できるエンコーディング)として扱われます。

下に示すコードでは、"C:\My Documents"フォルダ以下にあるすべてのHTMLファイル(拡張子が、".htm"または".html")から、「DOBON.NET」という文字列を含むファイルを大文字小文字を区別して検索しています。

VB.NET
コードを隠すコードを選択
'"DOBON.NET"を含むHTMLファイルを、大文字小文字を区別して探す
Dim files As System.Collections.ObjectModel.ReadOnlyCollection(Of String) = _
    My.Computer.FileSystem.FindInFiles( _
    "C:\My Documents", _
    "DOBON.NET", _
    False, _
    FileIO.SearchOption.SearchAllSubDirectories, _
    New String() {"*.htm", "*.html"})

'結果を表示
For Each f As String In files
    Console.WriteLine(f)
Next
C#
コードを隠すコードを選択
//参照にMicrosoft.VisualBasic.dllを追加する必要がある

//"DOBON.NET"を含むHTMLファイルを、大文字小文字を区別して探す
System.Collections.ObjectModel.ReadOnlyCollection<string> files =
    Microsoft.VisualBasic.FileIO.FileSystem.FindInFiles(
        "C:\\My Documents",
        "DOBON.NET",
        false,
        Microsoft.VisualBasic.FileIO.SearchOption.SearchAllSubDirectories,
        new string[] {"*.htm", "*.html"});

//結果を表示
foreach (string f in files)
{
    Console.WriteLine(f);
}

Grepを行う

My.Computer.FileSystem.FindInFilesメソッドが使えなかったり、Grep(正規表現を使用した検索)を行いたいときなどでは、自分でコードを書く必要があります。基本的には、DirectoryInfo.GetFilesで検索対象とするファイルを探し、ファイルの内容を読み込み、Regex.IsMatchで指定された正規表現パターンと一致するか調べるという流れになるでしょう。これらの方法については、以下のページで解説しています。

具体的な例を示します。ここでは、"C:\My Documents"フォルダにある拡張子が".html"のファイルの内、「DOBON.NET」という文字列が含まれているファイルを列挙しています。ごく簡単な例として参考にしてください。(ファイルを一度に読み込んでいますので、検索するファイルのサイズを制限するなどの対策が必要でしょう。)

VB.NET
コードを隠すコードを選択
'Button1のClickイベントハンドラ
Private Sub Button1_Click(ByVal sender As Object, _
        ByVal e As EventArgs) Handles Button1.Click
    'Grepの実行
    Dim files As String() = _
        Grep("C:\My Documents", "DOBON\.NET", "*.html", False)
    '結果の表示
    Dim f As String
    For Each f In files
        Console.WriteLine(f)
    Next f
End Sub

''' <summary>
''' Grepを行う
''' </summary>
''' <param name="dirPath">フォルダのパス。</param>
''' <param name="pattern">検索する正規表現のパターン。</param>
''' <param name="fileWildcards">対象とするファイル。</param>
''' <param name="ignoreCase">大文字小文字を区別するか。</param>
''' <returns>見つかったファイルパスの配列。</returns>
Public Shared Function Grep(ByVal dirPath As String, _
        ByVal pattern As String, ByVal fileWildcards As String, _
        ByVal ignoreCase As Boolean) As String()
    Dim fileCol As New System.Collections.ArrayList()

    '正規表現のオプションを設定
    Dim opts As System.Text.RegularExpressions.RegexOptions = _
        System.Text.RegularExpressions.RegexOptions.None
    If ignoreCase Then
        opts = opts Or System.Text.RegularExpressions.RegexOptions.IgnoreCase
    End If
    Dim reg As New System.Text.RegularExpressions.Regex(pattern, opts)

    'フォルダ内にあるファイルを取得
    Dim dir As New System.IO.DirectoryInfo(dirPath)
    Dim files As System.IO.FileInfo() = dir.GetFiles(fileWildcards)
    Dim f As System.IO.FileInfo
    For Each f In files
        '一つずつファイルを調べる
        If ContainTextInFile(f.FullName, reg) Then
            fileCol.Add(f.FullName)
        End If
    Next f

    Return CType(fileCol.ToArray(GetType(String)), String())
End Function

'ファイルの内容がpatternに一致するか調べる
Private Shared Function ContainTextInFile(ByVal filePath As String, _
        ByVal reg As System.Text.RegularExpressions.Regex) As Boolean
    'ファイルを読み込む
    Dim strm As System.IO.StreamReader = Nothing
    Dim txt As String = ""
    Try
        strm = New System.IO.StreamReader( _
            filePath, System.Text.Encoding.Default, True)
        txt = strm.ReadToEnd()
    Finally
        strm.Close()
    End Try

    Return reg.IsMatch(txt)
End Function
C#
コードを隠すコードを選択
//Button1のClickイベントハンドラ
private void Button1_Click(object sender, EventArgs e)
{
    //Grepの実行
    string[] files = Grep("C:\\My Documents", "DOBON\\.NET", "*.html", false);
    //結果の表示
    foreach (string f in files)
    {
        Console.WriteLine(f);
    }
}

/// <summary>
/// Grepを行う
/// </summary>
/// <param name="dirPath">フォルダのパス。</param>
/// <param name="pattern">検索する正規表現のパターン。</param>
/// <param name="fileWildcards">対象とするファイル。</param>
/// <param name="ignoreCase">大文字小文字を区別するか。</param>
/// <returns>見つかったファイルパスの配列。</returns>
public static string[] Grep(
    string dirPath, string pattern, string fileWildcards, bool ignoreCase)
{
    System.Collections.ArrayList fileCol =
        new System.Collections.ArrayList();

    //正規表現のオプションを設定
    System.Text.RegularExpressions.RegexOptions opts =
        System.Text.RegularExpressions.RegexOptions.None;
    if (ignoreCase)
        opts |= System.Text.RegularExpressions.RegexOptions.IgnoreCase;
    System.Text.RegularExpressions.Regex reg =
        new System.Text.RegularExpressions.Regex(pattern, opts);

    //フォルダ内にあるファイルを取得
    System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(dirPath);
    System.IO.FileInfo[] files = dir.GetFiles(fileWildcards);
    foreach (System.IO.FileInfo f in files)
    {
        //一つずつファイルを調べる
        if (ContainTextInFile(f.FullName, reg))
            fileCol.Add(f.FullName);
    }

    return (string[])fileCol.ToArray(typeof(string));
}

//ファイルの内容がpatternに一致するか調べる
private static bool ContainTextInFile(
    string filePath, System.Text.RegularExpressions.Regex reg)
{
    //ファイルを読み込む
    System.IO.StreamReader strm = null;
    string txt = "";
    try
    {
        strm = new System.IO.StreamReader(
            filePath, System.Text.Encoding.Default, true);
        txt = strm.ReadToEnd();
    }
    finally
    {
        strm.Close();
    }

    return reg.IsMatch(txt);
}

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • 「???を参照に追加します」の意味が分からないという方は、こちらをご覧ください。
  • Windows Vista以降でUACが有効になっていると、ファイルへの書き込みに失敗する可能性があります。詳しくは、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。