--- a/ffind Sat Sep 22 16:50:23 2012 -0400
+++ b/ffind Sat Sep 22 17:14:49 2012 -0400
@@ -12,6 +12,7 @@
import optparse
import string
import sys
+import re
from optparse import OptionParser, OptionGroup
@@ -20,6 +21,13 @@
CASE_INSENSITIVE = 2
CASE_SMART = 3
+BYTE = 1
+KILOBYTE = 1024 * BYTE
+MEGABYTE = 1024 * KILOBYTE
+GIGABYTE = 1024 * MEGABYTE
+TERABYTE = 1024 * GIGABYTE
+PETABYTE = 1024 * TERABYTE
+
VCS_DIRS = ['.hg', '.git', '.svn']
TYPE_FILE_REAL = 1
@@ -41,6 +49,10 @@
TYPES_ALL = TYPES_FILE | TYPES_DIR
+# Regexes ---------------------------------------------------------------------
+SIZE_RE = re.compile(r'^(\d+(?:\.\d+)?)([bkmgtp])?[a-z]*$', re.IGNORECASE)
+
+
# Global Options --------------------------------------------------------------
# (it's a prototype, shut up)
options = None
@@ -91,6 +103,16 @@
if query not in basename:
return False
+ if options.larger_than:
+ stat = os.stat(path)
+ if stat.st_size < options.larger_than:
+ return False
+
+ if options.smaller_than:
+ stat = os.stat(path)
+ if stat.st_size > options.smaller_than:
+ return False
+
if not options.binary:
with open(path) as f:
if '\0' in f.read(1024):
@@ -287,6 +309,35 @@
return result
+def parse_size(size):
+ size = size.replace(' ', '') if size else size
+
+ if not size:
+ return None
+
+ m = SIZE_RE.match(size)
+ if not m:
+ die('invalid size "%s"' % size)
+
+ n, unit = m.groups()
+
+ try:
+ n = float(n)
+ except ValueError:
+ die('invalid size "%s"' % size)
+
+ unit = {
+ 'b': BYTE,
+ 'k': KILOBYTE,
+ 'm': MEGABYTE,
+ 'g': GIGABYTE,
+ 't': TERABYTE,
+ 'p': PETABYTE,
+ }[unit or 'b']
+
+ return int(n * unit)
+
+
def main():
global options
@@ -322,6 +373,10 @@
# --type
options.type = build_type_set(options.type)
+ # --larger-than, --smaller-than
+ options.larger_than = parse_size(options.larger_than)
+ options.smaller_than = parse_size(options.smaller_than)
+
# Go!
search(query)