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='<!DOC TYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 FINAL//EN">'
©repStr='<!DOCT YPE HTML PUBLIC "-//W3C//DTD HTML 4.01
Transitional//EN">'
©
©def replaceStringIn File(findStr,re pStr,filePath):
© "replaces all findStr by repStr in file filePath"
© tempName=filePa th+'~~~'
© input = open(filePath)
© output = open(tempName,' w')
©
© for s in input:
© output.write(s. replace(findStr ,repStr))
© output.close()
© input.close()
© os.rename(tempN ame,filePath)
© print filePath
©
©def myfun(dummy, dirr, filess):
© for child in filess:
© if '.html' == os.path.splitex t(child)[1] and
©os.path.isfile (dirr+'/'+child):
© replaceStringIn File(findStr,re pStr,dirr+'/'+child)
©os.path.walk(m ydir, 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:
---------------------------------------
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::Path;
use File::Copy;
use Data::Dumper;
#-- arguments --
# the folder to be search on.
my $folderPath = q[/Users/t/web/UnixResource_di r];
# this is the backup folder path.
my $backupFolderPa th = 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'
$backupFolderPa th =~ s[/$][]; # e.g. '/tmp/joe_back';
$folderPath =~ m[/(\w+)$];
my $previousDir = $`; # e.g. '/home/joe'
my $lastDir = $1; # e.g. 'public_html'
my $backupRoot = $backupFolderPa th . '/' . $1; # e.g.
'/tmp/joe_back/public_html'
my $refLargeFiles = [];
my $totalFileChang edCount = 0;
#-- subroutines --
# fileFilterQ($fu llFilePath) return true if file is desired.
sub fileFilterQ ($) {
my $fileName = $_[0];
if ((-s $fileName) > $fileSizeLimit) {
push (@$refLargeFile s, $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::na me; # full path spect
my $currentDir = $File::Find::di r;
my $currentFileNam e = $_;
if (not fileFilterQ($cu rrentFile)) {
return 1;
}
# open file. Read in the whole file.
if (not(open FILE, "<$currentFile" )) {die("Error opening file:
$!");};
my $wholeFileStrin g;
{local $/ = undef; $wholeFileStrin g = <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 + ($wholeFileStri ng =~
s/$pattern/$findReplaceH{$ key1}/g);
};
if ($replaceCount > 0) { # replacement has happened
$totalFileChang edCount++;
# do backup
# make a directory in the backup path, make a backup
copy.
my $pathAdd = $currentDir; $pathAdd =~
s[$folderPath][];
mkpath("$backup Root/$pathAdd", 0, 0777);
copy($currentFi le,
"$backupRoo t/$pathAdd/$currentFileNam e") or
die "error: file copying file failed on
$currentFile\n$ !";
# write to the original
# get the file mode.
my ($mode, $uid, $gid) = (stat($currentF ile))[2,4,5];
# write out a new file.
if (not(open OUTFILE, ">$currentFile" )) {die("Error
opening file: $!");};
print OUTFILE $wholeFileStrin g;
if (not(close(OUTF ILE))) {die("Error closing file:
$!");};
# set the file mode.
chmod($mode, $currentFile);
chown($uid, $gid, $currentFile);
print "-----^$*%$@#-------------------------------\n";
print "$replaceCo unt replacements made at\n";
print "$currentFile\n ";
}
};
#-- main body --
find(\&processF ile, $folderPath);
print "--------------------------------------------\n\n\n";
print "Total of $totalFileChang edCount files changed.\n";
if (scalar @$refLargeFiles > 0) {
print "The following large files are skipped:\n";
print Dumper($refLarg eFiles);
}
__END__
Xah
xah@xahlee.org
directory.
here's the code:
©# -*- coding: utf-8 -*-
©# Python
©
©import os,sys
©
©mydir= '/Users/t/web'
©
©findStr='<!DOC TYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 FINAL//EN">'
©repStr='<!DOCT YPE HTML PUBLIC "-//W3C//DTD HTML 4.01
Transitional//EN">'
©
©def replaceStringIn File(findStr,re pStr,filePath):
© "replaces all findStr by repStr in file filePath"
© tempName=filePa th+'~~~'
© input = open(filePath)
© output = open(tempName,' w')
©
© for s in input:
© output.write(s. replace(findStr ,repStr))
© output.close()
© input.close()
© os.rename(tempN ame,filePath)
© print filePath
©
©def myfun(dummy, dirr, filess):
© for child in filess:
© if '.html' == os.path.splitex t(child)[1] and
©os.path.isfile (dirr+'/'+child):
© replaceStringIn File(findStr,re pStr,dirr+'/'+child)
©os.path.walk(m ydir, 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:
---------------------------------------
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::Path;
use File::Copy;
use Data::Dumper;
#-- arguments --
# the folder to be search on.
my $folderPath = q[/Users/t/web/UnixResource_di r];
# this is the backup folder path.
my $backupFolderPa th = 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'
$backupFolderPa th =~ s[/$][]; # e.g. '/tmp/joe_back';
$folderPath =~ m[/(\w+)$];
my $previousDir = $`; # e.g. '/home/joe'
my $lastDir = $1; # e.g. 'public_html'
my $backupRoot = $backupFolderPa th . '/' . $1; # e.g.
'/tmp/joe_back/public_html'
my $refLargeFiles = [];
my $totalFileChang edCount = 0;
#-- subroutines --
# fileFilterQ($fu llFilePath) return true if file is desired.
sub fileFilterQ ($) {
my $fileName = $_[0];
if ((-s $fileName) > $fileSizeLimit) {
push (@$refLargeFile s, $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::na me; # full path spect
my $currentDir = $File::Find::di r;
my $currentFileNam e = $_;
if (not fileFilterQ($cu rrentFile)) {
return 1;
}
# open file. Read in the whole file.
if (not(open FILE, "<$currentFile" )) {die("Error opening file:
$!");};
my $wholeFileStrin g;
{local $/ = undef; $wholeFileStrin g = <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 + ($wholeFileStri ng =~
s/$pattern/$findReplaceH{$ key1}/g);
};
if ($replaceCount > 0) { # replacement has happened
$totalFileChang edCount++;
# do backup
# make a directory in the backup path, make a backup
copy.
my $pathAdd = $currentDir; $pathAdd =~
s[$folderPath][];
mkpath("$backup Root/$pathAdd", 0, 0777);
copy($currentFi le,
"$backupRoo t/$pathAdd/$currentFileNam e") or
die "error: file copying file failed on
$currentFile\n$ !";
# write to the original
# get the file mode.
my ($mode, $uid, $gid) = (stat($currentF ile))[2,4,5];
# write out a new file.
if (not(open OUTFILE, ">$currentFile" )) {die("Error
opening file: $!");};
print OUTFILE $wholeFileStrin g;
if (not(close(OUTF ILE))) {die("Error closing file:
$!");};
# set the file mode.
chmod($mode, $currentFile);
chown($uid, $gid, $currentFile);
print "-----^$*%$@#-------------------------------\n";
print "$replaceCo unt replacements made at\n";
print "$currentFile\n ";
}
};
#-- main body --
find(\&processF ile, $folderPath);
print "--------------------------------------------\n\n\n";
print "Total of $totalFileChang edCount files changed.\n";
if (scalar @$refLargeFiles > 0) {
print "The following large files are skipped:\n";
print Dumper($refLarg eFiles);
}
__END__
Xah
xah@xahlee.org
Comment