Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > [perl-python] find & replace strings for all files in a dir

Reply
Thread Tools

[perl-python] find & replace strings for all files in a dir

 
 
Xah Lee
Guest
Posts: n/a
 
      01-31-2005
suppose you want to do find & replace of string of all files in a
directory.
here's the code:

©# -*- coding: utf-8 -*-
©# Python
©
©import os,sys
©
©mydir= '/Users/t/web'
©
©findStr='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 FINAL//EN">'
©repStr='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01
Transitional//EN">'
©
©def replaceStringInFile(findStr,repStr,filePath):
© "replaces all findStr by repStr in file filePath"
© tempName=filePath+'~~~'
© input = open(filePath)
© output = open(tempName,'w')
©
© for s in input:
© output.write(s.replace(findStr,repStr))
© output.close()
© input.close()
© os.rename(tempName,filePath)
© print filePath
©
©def myfun(dummy, dirr, filess):
© for child in filess:
© if '.html' == os.path.splitext(child)[1] and
©os.path.isfile(dirr+'/'+child):
© replaceStringInFile(findStr,repStr,dirr+'/'+child)
©os.path.walk(mydir, myfun, 3)


note that files will be overwritten.
be sure to backup the folder before you run it.

try to edit the code to suite your needs.

previous tips can be found at:
http://xahlee.org/perl-python/python.html

---------------------------------------
the following is a Perl version i wrote few years ago.
Note: if regex is turned on, correctness is not guranteed.
it is very difficult if not impossible in Perl to move regex pattern
around and preserve their meanings.


#!/usr/local/bin/perl

=pod

Description:
This script does find and replace on a given foler recursively.

Features:
* multiple Find and Replace string pairs can be given.
* The find/replace strings can be set to regex or literal.
* Files can be filtered according to file name suffix matching or other

criterions.
* Backup copies of original files will be made at a user specified
folder that preserves all folder structures of original folder.
* A report will be generated that indicates which files has been
changed, how many changes, and total number of files changed.
* files will retain their own/group/permissions settings.

usage:
1. edit the parts under the section '#-- arguments --'.
2. edit the subroutine fileFilterQ to set which file will be checked or

skipped.

to do:
* in the report, print the strings that are changed, possibly with
surrounding lines.
* allow just find without replace.
* add the GNU syntax for unix command prompt.
* Report if backup directory exists already, or provide toggle to
overwrite, or some other smarties.

Date created: 2000/02
Author: Xah

=cut

#-- modules --

use strict;
use File::Find;
use File:ath;
use File::Copy;
use Data:umper;

#-- arguments --

# the folder to be search on.
my $folderPath = q[/Users/t/web/UnixResource_dir];

# this is the backup folder path.
my $backupFolderPath = q[/Users/t/xxxb];

my %findReplaceH = (
q[<pre><a href="freebooks.html">back to Unix
Pestilence</a><pre>]=>q[<pre>? Back to <a href="freebooks.html">Unix
Pestilence</a></pre>],
);

# $useRegexQ has values 1 or 0. If 1, inteprets the pairs in
%findReplaceH
# to be regex.
my $useRegexQ = 0;

# in bytes. larger files will be skipped
my $fileSizeLimit = 500 * 1000;


#-- globals --

$folderPath =~ s[/$][]; # e.g. '/home/joe/public_html'
$backupFolderPath =~ s[/$][]; # e.g. '/tmp/joe_back';

$folderPath =~ m[/(\w+)$];
my $previousDir = $`; # e.g. '/home/joe'
my $lastDir = $1; # e.g. 'public_html'
my $backupRoot = $backupFolderPath . '/' . $1; # e.g.
'/tmp/joe_back/public_html'

my $refLargeFiles = [];
my $totalFileChangedCount = 0;

#-- subroutines --

# fileFilterQ($fullFilePath) return true if file is desired.
sub fileFilterQ ($) {
my $fileName = $_[0];

if ((-s $fileName) > $fileSizeLimit) {
push (@$refLargeFiles, $fileName);
return 0;
};
if ($fileName =~ m{\.html$}) {
print "processing: $fileName\n";
return 1;};

## if (-d $fileName) {return 0;}; # directory
## if (not (-T $fileName)) {return 0;}; # not text file

return 0;
};

# go through each file, accumulate a hash.
sub processFile {
my $currentFile = $File::Find::name; # full path spect
my $currentDir = $File::Find::dir;
my $currentFileName = $_;

if (not fileFilterQ($currentFile)) {
return 1;
}

# open file. Read in the whole file.
if (not(open FILE, "<$currentFile")) {die("Error opening file:
$!");};
my $wholeFileString;
{local $/ = undef; $wholeFileString = <FILE>;};
if (not(close(FILE))) {die("Error closing file: $!");};

# do the replacement.
my $replaceCount = 0;

foreach my $key1 (keys %findReplaceH) {
my $pattern = ($useRegexQ ? $key1 : quotemeta($key1));
$replaceCount = $replaceCount + ($wholeFileString =~
s/$pattern/$findReplaceH{$key1}/g);
};

if ($replaceCount > 0) { # replacement has happened
$totalFileChangedCount++;
# do backup
# make a directory in the backup path, make a backup
copy.
my $pathAdd = $currentDir; $pathAdd =~
s[$folderPath][];
mkpath("$backupRoot/$pathAdd", 0, 0777);
copy($currentFile,
"$backupRoot/$pathAdd/$currentFileName") or
die "error: file copying file failed on
$currentFile\n$!";

# write to the original
# get the file mode.
my ($mode, $uid, $gid) = (stat($currentFile))[2,4,5];

# write out a new file.
if (not(open OUTFILE, ">$currentFile")) {die("Error
opening file: $!");};
print OUTFILE $wholeFileString;
if (not(close(OUTFILE))) {die("Error closing file:
$!");};

# set the file mode.
chmod($mode, $currentFile);
chown($uid, $gid, $currentFile);

print "-----^$*%$@#-------------------------------\n";
print "$replaceCount replacements made at\n";
print "$currentFile\n";
}

};


#-- main body --

find(\&processFile, $folderPath);

print "--------------------------------------------\n\n\n";
print "Total of $totalFileChangedCount files changed.\n";

if (scalar @$refLargeFiles > 0) {
print "The following large files are skipped:\n";
print Dumper($refLargeFiles);
}


__END__
Xah
http://www.velocityreviews.com/forums/(E-Mail Removed)
http://xahlee.org/PageTwo_dir/more.html

 
Reply With Quote
 
 
 
 
YYusenet
Guest
Posts: n/a
 
      01-31-2005
Xah Lee wrote:
> suppose you want to do find & replace of string of all files in a
> directory.
> here's the code:

[snip]
> Xah
> (E-Mail Removed)
> http://xahlee.org/PageTwo_dir/more.html
>


When are you going to take the hint (from everybody in
comp.lang.perl.misc and comp.lang.python) to stop posting! Your posts
do not help anybody and will only hurt a beginner. *PLEASE STOP POSTING*!

--
k g a b e r t (@at@) x m i s s i o n (.dot.) c o m

* After "extensive" research, I noticed
* that (E-Mail Removed) received 12
* spam e-mail messages after just two
* posts on usenet groups. If you want
* to email me, use the "encrypted"
* email address at the beggining of my
* signature.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
How to replace all strings matching a pattern with correspondinglower case strings ? anonym Java 1 01-15-2009 07:29 PM
find out all .txt files in a dir recursively yihucd@gmail.com Perl Misc 17 11-12-2005 03:26 AM
how to replace string for all files under a dir? Guagua Perl Misc 10 08-16-2005 09:44 PM
Sub Dir, Virtual dir, what do I use? =?Utf-8?B?UnVkeQ==?= ASP .Net 0 06-12-2005 08:25 PM
[perl-python] find & replace strings for all files in a dir Xah Lee Perl Misc 0 01-31-2005 08:30 PM



Advertisments