Today some code: Mass find/insert on files

I needed a q&d app that could recurse subdirectories, find a given string in a given file type and then insert a new string just before the found string....

Specifically I was doing a horrible hack on a bunch of Sharepoint aspx templates, but it got the job done...

I haven't seen anything quite like this available on the net so I thought I'd throw it out there....

What it does: It's a console app that recursively crawls all the folders in a specificed directory tree, then searches for aspx files within those directories. It then analyzes the text of the aspx files, looking for one of two certain strings. If it finds it, the app then inserts another string just before the found string. Like I said this is quick and dirty, so all the variables of Path, Search strings, and Insert string are hard-coded. However it would be a trivial matter to move this code to a nice WinForm app and allow a user to input all that stuff..... This code is not optimized at all, but it did a search/insert on 1000+ documents in under a minute so I didn't bother...

Note, I wrote this for ASPX files. While it would be a simple matter to search other file types, my file handling assumes the max file length is an integer, and reads the entire file into memory as a single string. ie, large files will hose the pooch here and will either really eat memory, slow way down, or just crash the app.....

Standard disclaimers: If it hoses your work, your pc, your server, your job, or your life it's your fault. For education purposes only. There are no comments, if you don't understand what the code is doing, read and learn. Watch for line wraps! BACK UP YOUR FILES FIRST!

using System;

using System.IO;

using System.Collections;

using System.Text;

 

namespace ReplaceText

{

      /// <summary>

      /// Summary description for Class1.

      /// </summary>

      class Class1

      {

            static private string sPath = @"\\myserver\c$\mypath\mysubpath\etc ";

            static private string sNewText = @"Some text to insert

this can be multiple lines

of text or a single line

";

            static private string sSearchText = @"The text to search for

this can also be multiple lines of text";

            static private string sSearchTextAlt = @"An alternate

text to search for, also can be multiple. I needed this because

in some cases the files I was searching included quotes around
tags, in other cases there were no quotes.";

 

            static private int AnalyzedCount=0, ChangedCount=0;

            /// <summary>

            /// The main entry point for the application.

            /// </summary>

            [STAThread]

            static void Main(string[] args)

            {

 

                  Console.WriteLine("Gathering folder list");

                  DirectoryInfo diRoot = new DirectoryInfo(sPath);

 

                  ArrayList al = RecurseDirectories(diRoot);

                  al.Add(diRoot);

                  DirectoryInfo[] diChildren = new DirectoryInfo[al.Count];

 

                  al.CopyTo(diChildren);

                  Console.WriteLine(" Folder Scan Complete\n\rFound " + diChildren.Length.ToString() + " Folders");

 

                  foreach(DirectoryInfo di in diChildren)

                  {

                        ProcessFolder(di);

                  }

                  Console.WriteLine("Process Complete\n\rFiles Analyzed:" + AnalyzedCount.ToString() + "\n\rFiles Updated:" + ChangedCount.ToString());

                  Console.Read();

            }

 

            private static void ProcessFolder(DirectoryInfo diFolder)

            {

                  ASCIIEncoding AE = new ASCIIEncoding();

                  Console.WriteLine("Analyzing Folder: " + diFolder.Name);

                  FileInfo[] fiList = diFolder.GetFiles("*.aspx");

                  foreach(FileInfo fi in fiList)

                  {

                        AnalyzedCount++;

                        Console.Write("Checking File: " + fi.Name);

                        FileStream fs = fi.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);

                         

                        byte[] bytes = new byte[fi.Length-1];

                        fs.Read(bytes, 0, ((int) fi.Length-1));

                        string sFile = AE.GetString(bytes);

                        int ndx = sFile.IndexOf(sSearchText);

                        if(ndx == -1)

                              ndx = sFile.IndexOf(sSearchTextAlt);

 

                        if (ndx > -1)

                        {

                              ChangedCount++;

                              Console.Write(" Match - Updating");

                              //found search text

                              sFile = sFile.Insert(ndx, sNewText);

                              byte[] byFile = AE.GetBytes(sFile);

                              fs.Position=0;

                              fs.Write(byFile, 0, byFile.Length-1);

                              fs.Flush();

                        }

                        fs.Close();

                        Console.WriteLine("");

 

                  }

            }

 

            private static ArrayList RecurseDirectories(DirectoryInfo diParent)

            {

                  Console.Write("\rScanning: " + diParent.Name + "                                                        ");

                  ArrayList ret = new ArrayList(diParent.GetDirectories());

                  DirectoryInfo[] enumerateDir = new DirectoryInfo[ret.Count];

                  ret.CopyTo(enumerateDir);

                  foreach(DirectoryInfo di in enumerateDir)

                  {

                        ret.AddRange(RecurseDirectories(di));

                  }

                  return ret;

            }

 

      }

}

 

Print | posted on Monday, February 09, 2004 1:15 PM

Comments on this post

# re: Today some code: Mass find/insert on files

Requesting Gravatar...
You have a bug...

byte[] bytes = new byte[fi.Length-1];
fs.Read(bytes, 0, ((int) fi.Length-1));

This logic will truncate the last character off of each file that is modified. This code really should be:

byte[] bytes = new byte[fi.Length];
fs.Read(bytes, 0, ((int) fi.Length));

Left by Tony on Jan 30, 2006 3:31 PM

Your comment:

 (will show your gravatar)
 
Please add 2 and 5 and type the answer here: