else/Toolbox/fileswith.py

95 lines
2.6 KiB
Python
Raw Normal View History

2016-12-05 01:50:52 +00:00
'''
Search for a target string within the lines of files.
For example:
fileswith.py *.py "import random"
'''
2016-12-25 03:18:23 +00:00
import argparse
2016-11-18 06:24:52 +00:00
import fnmatch
import glob
import re
import sys
2016-12-02 06:37:07 +00:00
2016-12-23 03:42:21 +00:00
from voussoirkit import safeprint
2016-12-02 06:37:07 +00:00
from voussoirkit import spinal
2016-11-18 06:24:52 +00:00
2016-12-25 03:18:23 +00:00
2017-02-19 01:06:55 +00:00
def fileswith(
filepattern,
terms,
case_sensitive=False,
do_regex=False,
do_glob=False,
inverse=False,
match_any=False,
):
if not case_sensitive:
terms = [term.lower() for term in terms]
2016-12-25 03:18:23 +00:00
def term_matches(text, term):
return (
(term in text) or
(do_regex and re.search(term, text)) or
(do_glob and fnmatch.fnmatch(text, term))
)
2017-02-19 01:06:55 +00:00
anyall = any if match_any else all
2016-12-25 03:18:23 +00:00
generator = spinal.walk_generator(depth_first=False, yield_directories=True)
for filepath in generator:
if not fnmatch.fnmatch(filepath.basename, filepattern):
continue
2017-03-30 22:56:12 +00:00
if not filepath.is_file:
continue
2016-12-25 03:18:23 +00:00
handle = open(filepath.absolute_path, 'r', encoding='utf-8')
matches = []
try:
with handle:
for (index, line) in enumerate(handle):
2017-02-19 01:06:55 +00:00
if not case_sensitive:
compare_line = line.lower()
else:
compare_line = line
if inverse ^ anyall(term_matches(compare_line, term) for term in terms):
line = '%d | %s' % (index+1, line.strip())
2016-12-25 03:18:23 +00:00
matches.append(line)
except:
pass
if matches:
print(filepath.absolute_path)
safeprint.safeprint('\n'.join(matches))
print()
def fileswith_argparse(args):
return fileswith(
filepattern=args.filepattern,
terms=args.search_terms,
2017-02-19 01:06:55 +00:00
case_sensitive=args.case_sensitive,
2016-12-25 03:18:23 +00:00
do_glob=args.do_glob,
do_regex=args.do_regex,
2017-02-19 01:06:55 +00:00
inverse=args.inverse,
match_any=args.match_any,
2016-12-25 03:18:23 +00:00
)
def main(argv):
parser = argparse.ArgumentParser()
parser.add_argument('filepattern')
parser.add_argument('search_terms', nargs='+', default=None)
2017-02-19 01:06:55 +00:00
parser.add_argument('--any', dest='match_any', action='store_true')
parser.add_argument('--case', dest='case_sensitive', action='store_true')
2016-12-25 03:18:23 +00:00
parser.add_argument('--regex', dest='do_regex', action='store_true')
parser.add_argument('--glob', dest='do_glob', action='store_true')
2017-02-19 01:06:55 +00:00
parser.add_argument('--inverse', dest='inverse', action='store_true')
2016-12-25 03:18:23 +00:00
parser.set_defaults(func=fileswith_argparse)
args = parser.parse_args(argv)
args.func(args)
if __name__ == '__main__':
main(sys.argv[1:])