Multi-file Batch Editing

I’m looking for a simple Windows utility to edit a group of files in a batch mode. For example, you have a folder containing many html files and each contains the string “Copyright 2006” and you want to change them all to “Copyright 2007”. I imagine it might look something like sed in unix and be run from a command prompt like this:

utility filespec findtext replacetext

utility c:\my files*.htm “Copyright 2006” “Copyright 2007”

A simple GUI dialog would be even better. Any ideas or recommendations?

I’m not aware of any program that does this. That’s not to say there isn’t one, because there are a lot of programs I don’t know about.

However, as a general rule, unattended mass find and replace operations will almost always have some unintended results.

for %a in (.htm) * do <command> %a is how you might perform <command> on all .htm files in the current directory.

googlng ‘sed windows’ returns several results indicating that the program has been ported to Windows and is freely available. Couple such a utility wth the looping structure suggested by Usram and you should be able to do what you want pretty quickly

Try out Text Workbench (trialware).

I would use the sed option. Go for the Gnu Unix utilities and get sed. It’s only about 50k – in fact, I include that file in many of my custom application build folders to do stuff like you are describing.

However, the makers of my favorite Windows text editor, TextPad, seem to have a tool designed to do exactly what you are looking for called WildEdit. See it here.

FatBaldGuy, I know what you mean about the dangers of global search and replace. I’ve done it enough times in large Word documents to have picked up a few techniques here and there.

Usram, I haven’t seen that trick in years. It really brings me back to my DOS days. If that would work recursively into sub-directories I’d write up a batch file along with counsel wolf’s suggestion and be quite happy. (Sorry, I didn’t mention that requirement earlier.)

Thanks and_1. That does the trick (and a whole lot more).

I’m still curious if there’s a simpler utility out there somewhere.

Thanks. WildEdit looks like a winner too. Much simpler.

I use ReNamer, freeware from den4b. It’s a simple interface, extraordinary renaming tools, and it’lll let you preview the change before you apply it.

I think a /R switch to for will do the job.

Renamer is the best of the file renaming utilities - at least the best free one I could find - but the OP is talking about search and replace of text inside a collection of files, not in their filenames.

This can be done with VBScript. Here is an example of one to replace the text. It just needs to be modified slightly to loop through all files in a directory. I will work on it and see what I can do.

Here you go.

Ahh, yes. Paying attention would be a good thing. (Hey, it’s not my forum! I don’t have to read carefully.)

This won’t help the OP, but here’s a little perlscript I have that will recurse through a series of folders and do whatever you can command:


#! /usr/bin/perl

if (@ARGV < 2 || @ARGV > 3) {
	die "Usage: dorecurse \"<glob>\" \"<command>\"";
}

$curr_depth = 1;
if (@ARGV == 3) {
	$max_depth = $ARGV[2];
}
else {
	$max_depth = 100;
}

do_recurse();

sub do_recurse {
	foreach my $folder (glob "*") {
		if (-d $folder) {
			if ($curr_depth < $max_depth) {
				++$curr_depth;
				chdir("./$folder");
				do_recurse();
				chdir("..");
				--$curr_depth;
			}
		}
	}
	foreach my $file (glob $ARGV[0]) {
		if (-f $file) {
			my $command = $ARGV[1];
			$command =~ s/__FILE__/$file/g;
			if ($command =~ /__FILE(\d)__/) {
				my $remove = $1;
				$file = substr($file, 0, -$remove);
				$command =~ s/__FILE($remove)__/$file/g;
			}
			system($command);
		}
	}
}

You can do things like:

$ recursedo “*” “echo FILE
Will print out all filenames in the current folder and below.

$ recursedo “*.txt” “echo FILE” 1
Will print out all the *.txt files in the current folder only. ‘1’ controls how deep into the folder tree it should go.

$ recursedo “*.txt” “mv FILE FILE3.out”
Renamed all *.txt files to *.out in the current folder and all below. ‘3’ in the FILE macro indicates that the last three characters in the name should be dropped.

I assume that all this can be done with sed or whatever other tools are common to *nix systems, but at some point it’s easier to write off a perl script than to look up arcane *nix syntax. The perl should run on Windows systems as well without any porting.

I linked to the wrong article. This one is more pertinent.

Anyhow, here is a VBScript which should do what you want. Unlike a perlscript it does not require installing any additional software on Windows 2000 and newer.

Paste the code below into a text file with a .vbs extension. Customize the values of the indicated variables (strOriginal, strReplacement, strTargetDir, and strTargetExt). Double-clicking the file will then run a search-and-replace in all of the files in the selected directory.

Please test this carefully. Make absolutely sure you have the variables correct before running it. There is no Undo feature.


Dim strOriginal, strReplacement, strTargetDir, strTargetExt, objWMIService
Dim objFileList, objFile, objFSO, objTargetFile, strText, strNewText
Dim strFile, intLength, strEnd

'-----------------------------------------------------------------------------
'The text string to search for in each file.  Customize this value.
strOriginal = "Copyright 2006"

'The replacement text.  Customize this value.
strReplacement = "Copyright 2007"

'The directory which contains the target files.  Customize this value.
strTargetDir = "c:\my files"

'The file extension of the target files.  Customize this value.
strTargetExt = "htm"
'-----------------------------------------------------------------------------

Const ForReading = 1
Const ForWriting = 2

Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")

'Gets a list of all files in the target directory.
Set objFileList = objWMIService.ExecQuery _
    ("ASSOCIATORS OF {Win32_Directory.Name='" & strTargetDir & "'} Where " _
        & "ResultClass = CIM_DataFile")

'Loops through each file with the matching extension.
For Each objFile In objFileList
   If objFile.Extension = strTargetExt Then

	Set objFSO = CreateObject("Scripting.FileSystemObject")
	Set objTargetFile = objFSO.OpenTextFile(objFile.Name, ForReading)

	'Searches for the desired text.
	strText = objTargetFile.ReadAll
	objTargetFile.Close
	strNewText = Replace(strText, strOriginal, strReplacement)

	'Replaces the text.
	Set objTargetFile = objFSO.OpenTextFile(objFile.Name, ForWriting)
	objTargetFile.WriteLine strNewText
	objTargetFile.Close

	'Removes the two extra carriage returns that the previous section adds.
	Set objTargetFile = objFSO.OpenTextFile(objFile.Name, ForReading)
	strFile = objTargetFile.ReadAll
	objTargetFile.Close

	intLength = Len(strFile)
	strEnd = Right(strFile, 2)

	If strEnd = vbCrLf Then
    	    strFile = Left(strFile, intLength - 2)
    	    Set objTargetFile = objFSO.OpenTextFile(objFile.Name, ForWriting)
    	    objTargetFile.Write strFile
    	    objTargetFile.Close
	End If

   End If
Next

Wscript.Echo "Operation complete."