Skip to content

Instantly share code, notes, and snippets.

@TestItOnlyOnce
Last active January 11, 2019 13:10
Show Gist options
  • Save TestItOnlyOnce/2220942a82fc5ab6f31008aedb4ead61 to your computer and use it in GitHub Desktop.
Save TestItOnlyOnce/2220942a82fc5ab6f31008aedb4ead61 to your computer and use it in GitHub Desktop.
RegExp find and replace string in all matching files and subdirectories (recursive)
#------------------------------------------------------------------------------
# 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