8de084a9b64d

Implement file size filtering.
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Sat, 22 Sep 2012 17:14:49 -0400
parents db67c021a0d9
children 413a89f3b8ce
branches/tags (none)
files ffind

Changes

--- 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)