Last active
January 11, 2019 13:10
-
-
Save TestItOnlyOnce/2220942a82fc5ab6f31008aedb4ead61 to your computer and use it in GitHub Desktop.
RegExp find and replace string in all matching files and subdirectories (recursive)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#------------------------------------------------------------------------------ | |
# Filename: replace.py | |
# Purpose: RegExp find and replace string in all matching files and current subdirectories (recursive) | |
# Usage: python FindAndReplace.py "[Old Regexp]" "[New String]" | |
# [File Filters(ex/default: ".c,.cc,.h"")] [Working Directory] | |
# Requirement: Files must be text (non-binary) and not very large. | |
# WARNING: This script will OVERWRITE files matching [File Filters]. | |
# All occurrences of [Old Regexp] will be replaced with [New String]. | |
# Make sure you really, really want to do this!!! | |
#------------------------------------------------------------------------------ | |
import os | |
import sys | |
import traceback | |
import re | |
def usage(): | |
print('Usage: python FindAndReplace.py [Old RegExp] [New String] ' \ | |
'[File Filters (default: ".c,.cc,.h")] [Working Directory (default: ".")]') | |
def replaceStringInFile(fileName, oldStringRegexp, 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 | |
j = 0 | |
with open(fileName, 'r') as f: | |
i = 0 | |
newlines = [] | |
for line in f.readlines(): | |
i = len(re.findall(oldStringRegexp, line)) | |
if (i > 0) : | |
j = j + i | |
line = re.sub(oldStringRegexp, newString, line) | |
newlines.append(line) | |
# Write changes to same file | |
if (j > 0) : | |
print((" Found %d matches in " % j) + 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 false | |
return (j > 0) | |
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 = ['.c', '.cc', '.h'] | |
else: | |
stringFilter = sys.argv[3] | |
patterns = stringFilter.split(',') | |
if len(sys.argv) < 5: | |
path = DEFAULT_PATH | |
else: | |
path = sys.argv[4] | |
oldStringRe = re.compile(oldString, re.IGNORECASE | re.VERBOSE) | |
newString = newString.decode('string_escape') | |
print('') | |
print('Old RegExp : ' + oldStringRe.pattern) | |
print('New String : ' + newString) | |
print('File Filters : ' + ', '.join(patterns)) | |
print('Directory : ' + 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, oldStringRe, 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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment