Advertisement
Guest User

find_replace.py

a guest
Nov 14th, 2014
277
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.63 KB | None | 0 0
  1. ################################################################################
  2. #
  3. # find_replace.py - Finds and replaces all values keys in STR_DICT with their
  4. # corresponding value.  STR_DICT can be a list instead of dictionary if you
  5. # are not using the replace flag (-rep).  You can also populate STR_DICT with
  6. # a CSV file from the command line.  Use the -h or --help command line option
  7. # for usage instructions.
  8. #
  9. # Example usage with:
  10. #   1.) STR_DICT populated via CSV
  11. #   2.) Regex to ignore any file with ".git" in the name
  12. #   3.) Regex to match only ".c" and ".h" files
  13. #   4.) Recursive find (no replace) in the "D:\Git" directory
  14. #
  15. # python find_replace.py -csv "map.csv" -rec -reg_i "^.*?\.git.*$" -reg_m "^.*?\.[ch]$" "D:\Git"
  16. #
  17. # Use CMD instead of BASH if you are using the -reg_i or -reg_m flags.  BASH
  18. # chokes on the regex for some reason.
  19. #
  20. ################################################################################
  21.  
  22. import argparse
  23. import csv
  24. import os.path
  25. import re
  26. import sys
  27.  
  28. CSV = None
  29. FILE_CNT = 0
  30. LOG = 'find_replace.log'
  31. REPLACE = None
  32. RECURSE = None
  33. REGEX_FIND = None
  34. REGEX_IGNORE = None
  35. REGEX_MATCH = None
  36.  
  37. STR_DICT = {
  38. #   "FIND_THIS": "REPLACE_WITH_THIS",
  39. #   "ALSO_FIND_THIS": "REPLACE_WITH_THIS",
  40. }
  41.  
  42. def bldStrDict():
  43.     global STR_DICT
  44.  
  45.     # we are using a CSV file to populate STR_DICT, so reset it before we start
  46.     STR_DICT = dict()
  47.     with open(CSV, 'rb') as csvFile:
  48.         rows = csv.reader(csvFile, delimiter=getCsvDelimiter(), quotechar=getCsvQuoteChar())
  49.         for row in rows:
  50.             key = None
  51.             val = ''
  52.  
  53.             try:
  54.                 key = row[0]
  55.             except IndexError:
  56.                 pass
  57.  
  58.             try:
  59.                 val = row[1]
  60.             except IndexError:
  61.                 pass
  62.  
  63.             if key:
  64.                 STR_DICT[key] = val
  65.  
  66. def findAndReplace(inputs):
  67.     for input in inputs:
  68.         if os.path.isdir(input):
  69.             findAndReplaceInDir(input)
  70.         elif os.path.isfile(input):
  71.             findAndReplaceInFile(input)
  72.         else:
  73.             logAndPrint(input + ' does not exist')
  74.  
  75. def findAndReplaceInDir(dir):
  76.     if RECURSE:
  77.         fileCnt = 0
  78.         for root, dirs, files in os.walk(dir):
  79.             fileCnt = fileCnt + len(files)
  80.             for file in files:
  81.                 file = os.path.join(root, file)
  82.                 findAndReplaceInFile(file)
  83.     else:
  84.         for item in os.listdir(dir):
  85.             if os.path.isfile(os.path.join(dir, item)):
  86.                 findAndReplaceInFile(item)
  87.  
  88. def findAndReplaceInFile(file):
  89.     file = os.path.abspath(file)
  90.     if (not REGEX_MATCH or (REGEX_MATCH and re.search(REGEX_MATCH, file))) and (not REGEX_IGNORE or (REGEX_IGNORE and not re.search(REGEX_IGNORE, file))):
  91.         global FILE_CNT
  92.         FILE_CNT = FILE_CNT + 1
  93.  
  94.         f = None
  95.         s = None
  96.         try:
  97.             f = open(file,'r+')
  98.             s = f.read()
  99.         except:
  100.             logAndPrint('Couldn\'t open file ' + file)
  101.             return
  102.  
  103.         for oldStr in STR_DICT:
  104.             if (not REGEX_FIND and oldStr in s) or (REGEX_FIND and re.findall(oldStr, s)):
  105.                 if REPLACE:
  106.                     newStr = STR_DICT[oldStr]
  107.                     s = s.replace(oldStr, newStr)
  108.                     f.seek(0)
  109.                     f.write(s)
  110.                     f.truncate()
  111.                     logAndPrint('Updated ' + file)
  112.                 else:
  113.                     logAndPrint('Found ' + oldStr + ' in ' + file)
  114.         f.close()
  115.  
  116. def getCsvDelimiter():
  117.     delimiter = ','
  118.     with open (CSV, "r") as csvFile:
  119.         csvData = csvFile.read()
  120.         sniffer = csv.Sniffer()
  121.         try:
  122.             dialect = sniffer.sniff(csvData)
  123.             delimiter = dialect.delimiter
  124.         except:
  125.             pass
  126.     return delimiter
  127.  
  128. def getCsvQuoteChar():
  129.     quotechar = '"'
  130.     with open (CSV, "r") as csvFile:
  131.         csvData = csvFile.read()
  132.         sniffer = csv.Sniffer()
  133.         try:
  134.             dialect = sniffer.sniff(csvData)
  135.             quotechar = dialect.quotechar
  136.         except:
  137.             pass
  138.     return quotechar
  139.  
  140. def getHms(ms):
  141.     h, ms = divmod(ms, 3600000)
  142.     m, ms = divmod(ms, 60000)
  143.     s = float(ms) / 1000
  144.     return "%i:%02i:%06.3f" % (h, m, s)
  145.  
  146. def getTime():
  147.     import time
  148.     millis = int(round(time.time() * 1000))
  149.     return millis
  150.  
  151. def logAndPrint(s):
  152.     with open(LOG, 'a') as log:
  153.         log.write(s + '\n')
  154.     print s
  155.  
  156. def main():
  157.     # build the argument parser
  158.     startTime = getTime()
  159.     parser = argparse.ArgumentParser(prog='grep.py', description='This script will find/replace all instances of the keys in nameDict with their corresponding value in all the supplied files.  No special procesing is taking place, just a standard find/replace.'             )
  160.     parser.add_argument('-c',     '--csv',          action='store',      default=None, help='A CSV file that specifies find/replace pairs.  Find what is in column "A" and replace it with what is in column "B".'                                                                )
  161.     parser.add_argument('-rec',   '--recurse',      action='store_true', default=None, help='Recursive find in directories'                                                                                                                                                       )
  162.     parser.add_argument('-reg_f', '--regex_find',   action='store_true', default=None, help='The strings supplied for finding should be treated as regexes instead of plain text'                                                                                                 )
  163.     parser.add_argument('-reg_i', '--regex_ignore', action='store',      default=None, help='Regex that a file\'s absolute path must not match before find/replace is executed on file.  A file that matches both "match" regex and the "ignore" regex will be ignored.'          )
  164.     parser.add_argument('-reg_m', '--regex_match',  action='store',      default=None, help='Regex that a file\'s absolute path must match before find/replace is executed on file'                                                                                               )
  165.     parser.add_argument('-rep',   '--replace',      action='store_true', default=None, help='Find and replace as opposed to just find'                                                                                                                                            )
  166.     parser.add_argument('inputs',                                                      help='The files/directories to update',                                                                                                                                           nargs='+')
  167.     args = parser.parse_args()
  168.  
  169.     # get args
  170.     global CSV
  171.     CSV = args.csv
  172.     global RECURSE
  173.     RECURSE = args.recurse
  174.     global REGEX_FIND
  175.     REGEX_FIND = args.regex_find
  176.     global REGEX_IGNORE
  177.     REGEX_IGNORE = args.regex_ignore
  178.     global REGEX_MATCH
  179.     REGEX_MATCH = args.regex_match
  180.     global REPLACE
  181.     REPLACE = args.replace
  182.     inputs = args.inputs
  183.  
  184.     # prepare log
  185.     log = open(LOG, 'w+')
  186.     log.truncate()
  187.     log.close()
  188.  
  189.     # build STR_DICT
  190.     if CSV:
  191.         if os.path.isfile(CSV):
  192.             bldStrDict()
  193.         else:
  194.             logAndPrint(CSV + ' does not exist... aborting...')
  195.             return
  196.  
  197.     # do find and replace
  198.     findAndReplace(inputs)
  199.  
  200.     # log stats
  201.     stopTime = getTime()
  202.     runTime = stopTime - startTime
  203.     logAndPrint('searched ' + str(FILE_CNT) + ' files in ' + getHms(runTime))
  204.  
  205. if __name__ == "__main__":
  206.     sys.exit(main())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement