-
-
Save csmoore/15e46dedc5604c784b6d to your computer and use it in GitHub Desktop.
#------------------------------------------------------------------------------ | |
# Licensed under the Apache License, Version 2.0 (the "License"); | |
# you may not use this file except in compliance with the License. | |
# You may obtain a copy of the License at | |
# | |
# http://www.apache.org/licenses/LICENSE-2.0 | |
# | |
# Unless required by applicable law or agreed to in writing, software | |
# distributed under the License is distributed on an "AS IS" BASIS, | |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
# See the License for the specific language governing permissions and | |
# limitations under the License. | |
#------------------------------------------------------------------------------ | |
# Filename: FindAndReplace.py | |
# Purpose: Simple find and replace string in files (recursive) script | |
# Usage: python FindAndReplace.py [Old String] [New String] | |
# [File Filters(ex/default:".txt,.html,.erb")] [Directory To Check] | |
# Requirement: Files must be text (non-binary) files | |
# (this is why we force you to pick the file pattern/filter) | |
# WARNING: This will overwrite files matching [File Filters]. All occurrences of [Old String] | |
# will be replaced with [New String]. Make sure you really, really want to do this. | |
#------------------------------------------------------------------------------ | |
import os | |
import sys | |
import traceback | |
def usage(): | |
print('Usage: python FindAndReplace.py [Old String] [New String] ' \ | |
'[File Filters(default:".txt,.html,.erb")] [Directory To Check(.)]') | |
def replaceStringInFile(fileName, oldStringToReplace, newString): | |
if not(os.path.isfile(fileName) and os.access(fileName, os.W_OK)): | |
print("WARNING: Skipping...File does not exist or and is not writeable:" + fileName) | |
return False | |
fileUpdated = False | |
# credit/taken/adapted from: http://stackoverflow.com/a/4128194 | |
# Read in old file | |
with open(fileName, 'r') as f: | |
newlines = [] | |
for line in f.readlines(): | |
if (oldStringToReplace in line) : | |
fileUpdated = True | |
line = line.replace(oldStringToReplace, newString) | |
newlines.append(line) | |
# Write changes to same file | |
if fileUpdated : | |
print("String Found and Updating File: " + fileName) | |
try: | |
with open(fileName, 'w') as f: | |
for line in newlines: | |
f.write(line) | |
except: | |
print('ERROR: Cannot open/access existing file for writing: ' + fileName) | |
return fileUpdated | |
def main(): | |
try: | |
DEFAULT_PATH = '.' | |
if len(sys.argv) < 3: | |
usage() | |
# old/new string required parameters, exit if not supplied | |
sys.exit(-1) | |
else: | |
oldString = sys.argv[1] | |
newString = sys.argv[2] | |
if len(sys.argv) < 4: | |
patterns = ['.txt', '.html', '.erb'] | |
else: | |
stringFilter = sys.argv[3] | |
patterns = stringFilter.split(',') | |
if len(sys.argv) < 5: | |
path = DEFAULT_PATH | |
else: | |
path = sys.argv[4] | |
print('[Old String] : ' + oldString) | |
print('[New String] : ' + newString) | |
print('[File Filters] : ' + ', '.join(patterns)) | |
print('[Directory To Check] : ' + path) | |
if not os.path.exists(path): | |
raise Exception("Selected path does not exist: " + path) | |
# Walks through directory structure looking for files matching patterns | |
matchingFileList = \ | |
[os.path.join(dp, f) \ | |
for dp, dn, filenames in os.walk(path) \ | |
for f in filenames \ | |
if os.path.splitext(f)[1] in patterns] | |
print('Files found matching patterns: ' + str(len(matchingFileList))) | |
fileCount = 0 | |
filesReplaced = 0 | |
for currentFile in matchingFileList: | |
fileCount+=1 | |
fileReplaced = replaceStringInFile(currentFile, oldString, newString) | |
if fileReplaced: | |
filesReplaced+=1 | |
print("Total Files Searched : " + str(fileCount)) | |
print("Total Files Replaced/Updated : " + str(filesReplaced)) | |
except Exception as err: | |
print(traceback.format_exception_only(type(err), err)[0].rstrip()) | |
sys.exit(-1) | |
if __name__ == '__main__': | |
main() |
For a large file - I would probably restructure this script to read/write one line at a time.
So I was able to get the script to work. I have to add encoding for the read and write phases. And I went from 1174 ocurances of the OldString down to 11. And those are embedded into some xml tags. For which I just did a find/replace in Notepad++ as I wanted to get this script to my teammate.
Thanks!!
Glad you were able to get something working - I guess Notepad++ is indeed another option if it is a non-batch case - but then you never get the fun of learning to work with unicode
Ok so now you are being evil :) Putting a link to what seems to be a well crafted article on Unicode, gets me reading about it. And wanting to then use it. Almost like a real, grown up programmer. Which I am not by trade but am getting into more and more.
Thanks for the link. And for this script!
Hi
I tried to use your program to work with .xml file, and I am getting error. If possible plz check the below stackoverflow link for my query
Quick question:
Do you see the value of trying to rework the line.replace with string.replace?