Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Search and Replace Text in Multiple Files in Only 7 Lines

2 views
Skip to first unread message

TextDoctor

unread,
Apr 29, 2005, 8:22:06 AM4/29/05
to
Barry Block
27 April 2005
http://www.fireflysoftware.com/rdsearchreplace.htm

Have you ever needed to perform search / replace operations on multiple
files in a folder and all its subfolders? Have you ever needed to
search / replace text in a list of files? How about carrying out
multiple search / replace operations on a single file based on search /
replace pairs specified in a text file? This article shows how to do
each of these common search / replace operations using TEXTools--and
believe it or not--in only 7 lines of batch code!

To carry out each of these tasks, we'll be utilizing TEXTools (TCL.exe)
from a batch file. TEXTools is the perfect compliment to batch file
programming as it greatly extends the power of batch files. Without
implementing a single for loop, a TEXTools endowed batch file can
nonetheless easily process multiple files. This is made possible
because batch files can be constructed on-the-fly by another batch file
and then called by that batch file, (its kind of like a train that
builds its track as it goes). The reason that a for loop isn't needed
here to process multiple files is simply because TEXTools can take a
list of files that need to be processed and translate that list into a
batch file that, when run, results in the processing of each of the
files. For example, suppose we wanted to carry out some relatively
complex text editing operations on the following list of files:

myfile.txt
yourfile.txt
theirfile.txt
...

One way to do this would be to place the editing logic into a batch
file called procfile.bat and then process each file--one after the
other--using procfile.bat like this:

procfile.bat myfile.txt
procfile.bat yourfile.txt
procfile.bat theirfile.txt
...

That's great if you only have 3 files, but what if you have 100 or even
1000 files to process? That's where TEXTools comes into the picture.
If batch files are just text and they can be constructed on-the-fly,
then why not use TEXTools to turn our list of filenames into a batch
file that, when run, results in the processing of each of the files?
If a batch file like procfile.bat is going to be employed in the
process anyway, then we're already half-way to our goal. What we want
is for the list of file names to be preceded by "procfile.bat" with one
change--procfile.bat needs to be called. Now we have a batch file that
will do all the work for us:

call procfile.bat myfile.txt
call procfile.bat yourfile.txt
call procfile.bat theirfile.txt
...

Of course, this is the kind of thing that TEXTools excels at doing.
Adding the text, "call procfile.bat " to the front of every line in a
text file containing hundreds of file names--in order to create and
execute an on-the-fly batch file is a snap:

type ListOfFiles.txt | tcl InsStr 1 'call procfile.bat ' >t$1.bat
call t$1.bat

We're now ready to tackle our assignment except for one missing puzzle
piece. We need our procfile.bat. Ours needs to take as arguments a
file name, a search text and a replacement text:

ProcFile <file name> <search text> <replacement text>

Internally, ProcFile.bat will edit the given file by replacing all
occurrences of <search text> with <replacement text> inside the file.
Fundamentally, this could be done with just two lines of code (under
Windows 95 and 98, etc. this could be done in a single line without the
need of a temporary intermediate file):

type %1 | tcl "ReplStr '%2' '%3'" >t$1.txt
type t$1.txt >%1

In reality, we need a bit more than this though. What if the search
text or replacement text is specified having embedded blanks? This can
only be done at the command prompt by using surrounding double-quotes
like so:

ProcFile myfile.txt "red car" "blue car"

The problem is that these surrounding double-quotes are part of the
parameter as far as Windows is concerned. As far as we're concerned
however, they're not and so we must get rid of them. Again, this is a
simple matter using TEXTools:

echo %2| tcl "ReplStr '#22' '' | InsStr 1 'set search='" >t$1.bat
echo %3| tcl "ReplStr '#22' '' | InsStr 1 'set replace='" >>t$1.bat
call t$1.bat

These three magical lines simply remove the surrounding double-quotes
from each of the search / replace parameters that are passed into
ProcFile. Not that the parameters themselves are altered in any way.
Their unquoted contents are merely copied into environment variables!
Note again the use of an on-the-fly batch file to accomplish this.
Laying down tracks...

So now, our ProcFile.bat looks something like this:

:: Remove any surrounding double-quotes from the search/replace
text...

echo %2| tcl "ReplStr '#22' '' | InsStr 1 'set search='" >t$1.bat
echo %3| tcl "ReplStr '#22' '' | InsStr 1 'set replace='" >>t$1.bat
call t$1.bat

:: Perform text replacements on this file...

type %1 | tcl "ReplStr '%search%' '%replace%'" >t$1.txt
type t$1.txt >%1

Bear in-mind that this is a bare-bones implementation of ProcFile.bat.
Normally, you'd include some logic to abort execution if all parameters
weren't supplied, etc. but this is just a demonstration. For the
actual batch files, see the "Search and Replace" examples available in
the TEXTools download package (installed beneath the "Sample Scripts"
folder) and also available online at
www.fireflysoftware.com\TEXTools\examples.htm. Now, on to bigger and
better things...

Using a Recursive File Search

Now that we have a batch file that performs text replacements on a
single file, how can we employ it to process all files in a given
folder and its subfolders? The key to this lies in the DIR command.
When used with the /b and /s switches, the DIR command lists (fully
qualified) all files in a folder (and all its subfolders) that match a
given file specification. Imagine that... a list of all the files in a
given folder and its subfolders that match say, the file specification,
"work*.txt"! In practical terms that translates into a gem like this:

dir %1 /b /s | tcl "InsStr 1 'call ProcFile.bat #22' | AppendStr
'#22 %2 %3'" >t$2.bat
call t$2.bat

Here's a batch file (say, "Recursive.bat") that can be called as
follows:

Recursive work*.txt "this" "that"

Here, it would replace all instances of "this" with "that" in all files
(in the current folder and subfolders) matching "work*.txt". Not bad
for 7 lines of batch code, eh?

Using a List of Files

If the files to be edited are listed in a text file, the batch code
needed to process them is almost identical to the above:

type %1 | tcl "InsStr 1 'call ProcFile.bat #22' | AppendStr '#22 %2
%3'" >t$2.bat
call t$2.bat

The only difference is in where the list of files originates. With
this approach, all you need is a list of files in a text file to
process. Such a batch file might be called like this:

ProcFileList FileList.txt "this" "that"

This would replace all instances of "this" with "that" in all of the
files listed in FileList.txt.

Using a List of Replacements

This last example of search and replace performs multiple edits on a
single file by utilizing a file containing multiple search / replace
pairs. Again, a call to ProcFile is all that is needed:

type %2 | tcl "InsStr 1 'call ProcFile.bat %1 '" >t$2.bat
call t$2.bat

Such a batch file as this might be called ProcReplList.bat. Here's how
it would be called to perform multiple search / replacement operations
on MyFile.txt using the search / replace pairs found in
Replacements.txt:

ProcReplList MyFile.txt Replacements.txt

Note: Each of the above search / replace examples can be found online
at www.fireflysoftware.com\TEXTools\examples.htm or inside the TEXTools
download package, (installed beneath the "Sample Scripts" folder).

Permission is granted to freely post or distribute this article so long
as it is unedited and credit and copyright information is left intact.

Copyright © 2005 Firefly Software

http://www.fireflysoftware.com/rdsearchreplace.htm

0 new messages