Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 146 lines (125 sloc) 4.56 KB
#!/usr/bin/env python
# Photo Search:
# Search under the current dir, or the first argument given,
# for grep matches within files named "Keywords".
# Then translate that to a list of full pathnames.
# Copyright 2007,2009 by Akkana Peck: share and enjoy under the GPLv2 or later.
# Wish list: Boolean logic. Currently this can search only for one
# term/phrase at a time.
from __future__ import print_function
import sys, os, string
def search_for_keywords(grepdirs, orpats, andpats, notpats, separate) :
'''Inside grepdirs, open files named Tags or Keywords.
Search those lines looking for matches in the keywords for pats.
'''
results = []
for d in grepdirs:
for root, dirs, files in os.walk(d) :
if not files :
continue
for f in files :
if f == "Tags" or f == "Keywords":
search_for_keywords_in(root, f, orpats, andpats, notpats,
separate, results)
break # Would prefer to break out of this root, not f
return results
def search_for_keywords_in(d, f, orpats, andpats, notpats, separate,
results=None) :
'''Search in d/f for lines matching or, and and not pats.
Those have lines in a format like:
[tag ]keyword, keyword: file.jpg file.jpg
If results is passed in, append to it, else just print.
'''
filetags = {}
for line in open(os.path.join(d, f)):
line = line.strip()
if not line:
continue
if line.startswith("tag "):
line = line[4:]
elif line.startswith("category "):
continue
# Now we know it's a tag line.
parts = line.split(':')
if len(parts) < 2:
continue
tags = parts[0].strip()
# There may be several comma-separated tags here, but we
# actually don't care about that for matching purposes.
for imgfile in parts[1].strip().split():
fullpath = os.path.join(d, imgfile)
if fullpath.startswith('./'):
fullpath = fullpath[2:]
if not os.path.exists(fullpath):
continue
if fullpath not in list(filetags.keys()):
filetags[fullpath] = tags
else:
filetags[fullpath] += ', ' + tags
# Now we have a list of tagged files in the directory, and their tags.
for imgfile in list(filetags.keys()):
tags = filetags[imgfile]
if has_match(tags, orpats, andpats, notpats):
if results != None:
results.append(imgfile)
elif separate:
print(tags, ':', imgfile)
else:
print(imgfile, end=' ')
def has_match(tags, orpats, andpats, notpats):
'''Do the tags contain any of the patterns in orpats,
AND all of the patterns in andpats,
AND none of the patterns in notpats?
'''
#print "Looking for OR", orpats, "AND", andpats, "NOT", notpats, "IN", tags
for pat in notpats:
if pat in tags:
return False
for pat in andpats:
if pat not in tags:
return False
if not orpats:
return True
for pat in orpats:
if pat in tags:
return True
return False
if __name__ == "__main__":
# Sadly, we can't use argparse if we want to be able to use -term
# to indicate "don't search for that term".
def Usage():
print('''Usage: %s [-s] condition [condition ...]
Search for files matching patterns in Tags or Keywords files.
Conditions can include three types of patterns:
1. Starts with +: must be present (AND).
2. Starts with -: must NOT be present (NOT).
3. Starts with neither: one of these must be present (OR).
Optional arguments:
-s, --separate print separate lines from different tag files
Copyright 1009,2014 by Akkana Peck; share and enjoy under the GPL v2 or later.''' % os.path.basename(sys.argv[0]))
sys.exit(0)
args = sys.argv[1:]
if args[0] == '-h' or args[0] == '--help':
Usage()
if args[0] == '-s':
separate = True
args = args[1:]
else:
separate = False
andpats = []
orpats = []
notpats = []
for pat in args:
if pat[0] == '+':
andpats.append(pat[1:])
elif pat[0] == '-':
notpats.append(pat[1:])
else:
orpats.append(pat)
r = search_for_keywords(['.'], orpats, andpats, notpats, separate)
s = set(r)
r = list(s)
r.sort()
for f in r:
print(f, end=' ')
print()