Search files in a directory hierarchy for a target string in C#

I’m using Windows 8 now, but my Windows 7 installation was never able to search properly inside certain kinds of files such as .cs files, so I wrote this program to search files for a target string. It recursively searches files in a directory hierarchy to find a target string. It can search just about any kind of file, even if it doesn’t contain text the way Windows understand it. For example, it can search DLLs and executable files to see if they happen to contain a string.

The ListFiles method shown in the following code does most of the work.

// Add the files in this directory's subtree 
// that match the pattern to the ListBox.
private void ListFiles(ListBox lst, string pattern,
    DirectoryInfo dir_info, string target)
{
    // Get the files in this directory.
    FileInfo[] fs_infos = dir_info.GetFiles(pattern);
    foreach (FileInfo fs_info in fs_infos)
    {
        if (target.Length == 0)
        {
            lstResults.Items.Add(fs_info.FullName);
        } 
        else
        {
            string txt = File.ReadAllText(fs_info.FullName);
            if (txt.IndexOf(target, StringComparison.OrdinalIgnoreCase) >= 0)
            {
                lstResults.Items.Add(fs_info.FullName);
            }
        }
    }

    // Search subdirectories.
    DirectoryInfo[] subdirs = dir_info.GetDirectories();
    foreach (DirectoryInfo subdir in subdirs)
    {
        ListFiles(lst, pattern, subdir, target);
    }
}

ListFiles takes as a parameter a DirectoryInfo representing the directory where the search should start. It uses that object’s GetFiles method to get a list of files that match the file pattern. If there is no target string to look for, the program simply adds the files to the result list.

If there is a target string, the program uses File.ReadAllText to read the file’s contents into a string. If the target is in the string, the program adds the file to the list. The program uses the IndexOf method instead fo Contains so it can use the OrdinalIgnoreCase parameter to ignore case while looking for matches.

After searching the files in this directory, the program uses the DirectoryInfo object’s GetDirectories method to get a list of its subdirectories. The program calls ListFiles recursively to search each subdirectory.

That’s all there is to the searching code, but the program does one more interesting thing. When it starts, it uses the following code to determine whether it was executed from the Send To menu.

// If we launched from the Send To menu,
// use the argument as our directory.
private void Form1_Load(object sender, EventArgs e)
{
    if (System.Environment.GetCommandLineArgs().Length > 1)
    {
        txtDirectory.Text = System.Environment.GetCommandLineArgs()[1];
        txtTarget.Focus();
    }
}

This code checks the program’s command line arguments. The first argument is always the name of the executing program. If there is a second argument, then it should be the name of a directory dragged onto the executable or sent to the program via the Send To menu. If there is a second argument, the program places it in its Directory text box.

To make using this program easy, I added it to my Send To menu. Then I can right-click a directory, open the Send To menu, and select this program to make it search the directory. For more information on adding items to the Send To menu, see Add items to the Send To menu.

The result isn’t as fancy as Windows Explorer’s search. You can’t search by file date, size, author, rating, or any of the other zillion things you would never want to use in a search. You can add those features if you like.

However, this program works and can search any kind of file. It’s even a lot faster than the Windows search.






This entry was posted in files, strings, system. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *