Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- #######################################################################
- #
- # The following license supersedes all notices in the source code.
- #
- # Copyright (c) 2021 Kurt Dekker/PLBM Games All rights reserved.
- #
- # @kurtdekker - http://www.plbm.com
- #
- # Redistribution and use in source and binary forms, with or without
- # modification, are permitted provided that the following conditions are
- # met:
- #
- # Redistributions of source code must retain the above copyright notice,
- # this list of conditions and the following disclaimer.
- #
- # Redistributions in binary form must reproduce the above copyright
- # notice, this list of conditions and the following disclaimer in the
- # documentation and/or other materials provided with the distribution.
- #
- # Neither the name of the Kurt Dekker/PLBM Games nor the names of its
- # contributors may be used to endorse or promote products derived from
- # this software without specific prior written permission.
- #
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- #
- #####################################################################
- #
- # I cannot believe how irritating it is to search all *.TXT files in
- # a posix environment, with huge clumsy find/for/grep combo chains.
- #
- # This is intended to make a nice simple way of doing things.
- #
- #####################################################################
- #
- import os, sys, fnmatch
- from string import maketrans
- import re
- def main():
- argcopy = list(sys.argv[1:])
- option_showfile = 0 # put the file ON the same line
- option_fileonly = 0 # only display the filename
- option_matchcase = 0
- option_count = 0
- filepatterns = "*"
- if len(argcopy) < 2:
- print "Usage: %s [-f] [!]searchtext filepattern[,pattern2,pattern3]" % sys.argv[0]
- print " where ! will search for lines NOT containing searchtext"
- print " options: -f display filename"
- print " options: -l display filename only"
- print " options: -c count occurrences only"
- print " options: -m enforce correct case"
- print
- print "Example: (always escape wildcards on Posix systems)"
- print "$ grp kurt \*.txt"
- print "$ grp MyFunctionName \*.cs"
- exit()
- while len(argcopy[0]) > 1 and argcopy[0][0] == '-':
- if len(argcopy[0]) > 1:
- if argcopy[0][1] == 'f':
- option_showfile = 1
- print >> sys.stderr, "option_showfile enabled"
- if argcopy[0][1] == 'l':
- option_fileonly = 1
- print >> sys.stderr, "option_fileonly enabled"
- if argcopy[0][1] == 'c':
- option_count = 1
- option_fileonly = 1
- print >> sys.stderr, "option_count enabled"
- if argcopy[0][1] == 'm':
- option_matchcase = 1
- print >> sys.stderr, "option_matchcase enabled"
- argcopy = argcopy[1:]
- searchtext = argcopy[0]
- argcopy = argcopy[1:]
- invert = 0
- if len(searchtext) > 0:
- if searchtext[0] == '!':
- searchtext = searchtext[1:]
- invert = 1
- filepatterns = argcopy[0].lower()
- if (not option_matchcase):
- searchtext = searchtext.lower()
- matches = []
- for root, dirnames, filenames in os.walk('.'):
- fnpairs = [(a.lower(),a) for a in filenames]
- for filepattern in filepatterns.split( ","):
- files = [fo for (fl,fo) in fnpairs if fnmatch.fnmatch(fl, filepattern)]
- for n in xrange( len( files)):
- oneline = os.path.join(root, files[n])
- if ((oneline.find( ".hg") < 0) and
- (oneline.find( ".git") < 0) and
- (oneline.find( ".DS_Store") < 0) and
- (oneline.find( ".DSStore") < 0) and
- True):
- matches.append(oneline)
- tabtospacett = maketrans( '\t', ' ')
- anyfoundatall = 0
- output = []
- reignorecaseflags = re.IGNORECASE
- if option_matchcase:
- reignorecaseflags = 0
- reflags = reignorecaseflags
- rematcher = re.compile( ".*" + searchtext + ".*", reflags)
- for fn in matches:
- didfilename = 0
- foundany = 0
- count = 0
- try:
- with open( fn) as fp:
- for oneline in [a[:-1] for a in fp.readlines()]:
- foundmatch = oneline.lower().find( searchtext) >= 0
- rematched = rematcher.match( oneline)
- if rematched:
- foundmatch = 1
- if option_matchcase:
- foundmatch = oneline.find( searchtext) >= 0
- if invert:
- foundmatch = not foundmatch
- if foundmatch:
- count += 1
- foundany = 1
- anyfoundatall = 1
- if option_showfile or not didfilename:
- didfilename = 1
- output.append( "File: %s: " % fn)
- if not option_fileonly:
- while len(oneline) and (oneline[-1] in ('\n', '\r',)):
- oneline = oneline[:-1]
- output.append( oneline.translate(tabtospacett))
- except:
- print "Unable to open " + fn + " for reading..."
- if invert:
- if not foundany:
- output.append( "File: %s:" % fn)
- if option_count:
- if count > 0:
- output.append( "%u" % count)
- if not anyfoundatall:
- print >> sys.stderr, "Don't forget to quote glob chars on Posix shells."
- else:
- if option_fileonly:
- outout = sorted(output)
- for o in output:
- print o
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement