Quick and Dirty C# Recursive Find and Replace

Say you had a vast Visual Studio solution of something ridunculous like 120+ projects and wanted to test out a few proofs of concept on improving build times.

Now say that one of the proofs of concept was to use a shared bin folder for all projects in a single solution. Editing 120+ proj files is going to make you a little crazy.

How about a little recursive find-and-replace app using regular expressions (my saviour in many menial text manipulation tasks) to do it all for you? That’d be nice, wouldn’t it? That’s what I thought too. So I just did a quick and dirty console app to do just that.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Collections.ObjectModel;

namespace RecursiveFindAndReplace
{
    class Program
    {
        static void Main(string[] args)
        {
            // where to start your directory walk
            var directoryToTraverse = @"C:\VisualStudio2010\Projects\TestSolutionWithLoadsOfProjectsInIt\";

            // what files to open
            var fileTypeToOpen = "*.csproj";

            // what to look for
            var patternToMatch = @"<OutputPath>bin\\[a-zA-Z]*\\</OutputPath>;";
            var regExp = new Regex(patternToMatch);
            // the new content
            var patternToReplace = @"<OutputPath>;C:\bin\$(Configuration)\</OutputPath>";

            // get all the files we want and loop through them
            foreach (var file in GetFiles(directoryToTraverse, fileTypeToOpen))
            {
                // open, replace, overwrite
                var contents = File.ReadAllText(file);
                var newContent = regExp.Replace(contents, patternToReplace);
                File.WriteAllText(file, newContent);
            }
        }

        // recursive method to return the files we want in all sub dirs of the initial root
        static List<string> GetFiles(string directoryPath, string extension)
        {
            var fileList = new List<string>();
            foreach (var subDir in Directory.GetDirectories(directoryPath))
            {
                fileList.AddRange(GetFiles(subDir, extension));
            }

            fileList.AddRange(Directory.GetFiles(directoryPath, extension));

            return fileList;
        }

    }
}

No doubt this could be made prettier with a little lambda, but like I said – quick and dirty.

—————–

Edit: I’ve just realised that Directory.GetFiles is inherently recursive. Duh. So the foreach instead becomes:

// get all the files we want and loop through them
foreach (var file in Directory.GetFiles(directoryToTraverse
            ,fileTypeToOpen
            ,SearchOption.AllDirectories))
{
    // open, replace, overwrite
    var contents = File.ReadAllText(file);
    var newContent = regExp.Replace(contents, patternToReplace);
    File.WriteAllText(file, newContent);
}

So that’s even quicker and slightly less dirty. Ah well.

Leave a Reply

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