Skip to content

Instantly share code, notes, and snippets.

@theodoregoetz
Created November 20, 2015 16:59
Show Gist options
  • Save theodoregoetz/c378a2ebfdadb6a36850 to your computer and use it in GitHub Desktop.
Save theodoregoetz/c378a2ebfdadb6a36850 to your computer and use it in GitHub Desktop.
Find-Grep python script
#!/usr/bin/python3
import sys
import os
import argparse
import fnmatch
import re
class AppendAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
if getattr(namespace, self.dest) == self.default:
items = []
else:
items = argparse._copy.copy(argparse._ensure_value(namespace, self.dest, []))
items.append(values)
setattr(namespace, self.dest, items)
parser = argparse.ArgumentParser()
parser.add_argument('-c', '--case',
default=False,
action='store_true',
help='make search case-sensitive')
parser.add_argument('-l', '--follow-links',
default=False,
action='store_true',
help='follow symbolic links')
parser.add_argument('-i', '--ignore',
default=['.svn','_build'],
metavar='pattern',
action=AppendAction,
help='path pattern(s) to ignore (default: .svn _build)')
parser.add_argument('-p', '--paths',
default=['*.cpp','*.h*'],
metavar='pattern',
action=AppendAction,
help='path pattern(s) to search for (default: *.cpp *.h*)')
parser.add_argument('directories',
default=['.'],
nargs='*',
metavar='dir',
help='directories to search (default: .)')
parser.add_argument('pattern',
metavar='pattern',
help='pattern to look for in files')
parser.add_argument('-v','--verbose',
default=False,
action='store_true',
help='verbose output')
args = parser.parse_args()
if args.verbose:
print('''\
case-sensitive: {case}
follow links: {follow_links}
ignore: {ignore}
paths: {paths}
directories: {directories}
pattern: {pattern}'''.format(**vars(args)))
for d in args.directories:
if not os.path.isdir(d):
raise Error('{} is not a directory'.format(d))
flags = []
if not args.case:
flags.append(re.IGNORECASE)
pattern = re.compile('^.*'+args.pattern+'.*$', *flags)
for d in sorted(args.directories):
for root,dirs,files in os.walk(d,followlinks=args.follow_links):
for p in args.ignore:
for x in fnmatch.filter(dirs,p):
dirs.remove(x)
dirs = sorted(dirs)
for p in args.paths:
for f in sorted(fnmatch.filter(files,p)):
filepath = os.path.join(root,f)
try:
lines = open(filepath,'r').readlines()
except UnicodeDecodeError:
lines = open(filepath,'r',encoding='latin-1').readlines()
for linenumber,linestring in enumerate(lines):
if pattern.match(linestring) is not None:
sys.stdout.write('{}:{}:{}'.format(filepath,linenumber+1,linestring))
@theodoregoetz
Copy link
Author

Tired of typing shenanigans like this?

find dir1 dir2 -name '*.cpp' -name '*.h*' | grep -v '.svn' | xargs grep -Hin my_function_name

Do you find such commands too slow? Just try this python script which seems to run many times faster!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment