bugfindutils - Bugs: bug #12162, Enhancement req: finding files...

 
 

bug #12162: Enhancement req: finding files less than 2Gb in size [needs community feedback]

Submitter:  James Youngman <jay>
Submitted:  Sun 27 Feb 2005 11:11:33 AM UTC
   
 
Category:  find Severity:  1 - Wish
Item Group:  None Status:  Need Info
Privacy:  Public Assigned to:  jay
Originator Name:  Amir Open/Closed:  Open
Release:  4.1.20 Fixed Release:  None
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Fri 08 Jul 2016 07:06:15 AM UTC, comment #31: 


>I am totally happy with -filesize option suggestion, yet, it would be
>important to also have comparing bigger, smaller or equal.
>How would you solve this?


>I suggest:


>-size lt 1M: less than one MiB (< 1048576 bytes, 1048575 matches 1048576 does not match)
>-size lte 1M: less than or equal one MiB (<= 1048576 bytes)
>-size gt 1M: more than one MiB (> 1048576 bytes)
>-size gte 1M: more or equal than one MiB (>= 1048576 bytes)
>-size eq 1M: exactly one MiB (=1048576 bytes)

Your suggestion is interesting and more ambitious.  So far i have restricted
myself to bring the behaviour that many people are looking for, causing
most of the bug reports/stackoverflow questions:
A new predicate size without rounding.

(Once we have this solved we always could think how to extend these
predicates to allow things as <= or >=).

I follow the Nigel suggestion (#16 in this thread).

Below is my patch:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

From 6ec1877385228aa5cd540c26fbebf09ba283654b Mon Sep 17 00:00:00 2001
From: Tino Calancha <tino.calancha@gmail.com>
Date: Fri, 8 Jul 2016 13:01:54 +0900
Subject: [PATCH 1/4] Merge with remote rep

---
 gnulib | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gnulib b/gnulib
index 97173b2..0ef1689 160000
--- a/gnulib
+++ b/gnulib
@@ -1 +1 @@
-Subproject commit 97173b26d27d9f31de1789e994dfe014e3a40162
+Subproject commit 0ef1689f914462d778c5e279dfc48702fecbabbf
--
2.8.1

From 897fe8422701651af0c022aff797ff3aec5ff14d Mon Sep 17 00:00:00 2001
From: Tino Calancha <tino.calancha@gmail.com>
Date: Fri, 8 Jul 2016 14:39:27 +0900
Subject: [PATCH 2/4] Predicate size without rounding

  • find/defs.h: New predicate filesize; as predicate size but

without rounding (Bug #12162).

  • find/parser.c: Idem.
  • find/pred.c: Idem.
  • find/tree.c: Idem.

---
 find/defs.h   |  1 +
 find/parser.c | 15 +++++++++++----
 find/pred.c   | 28 ++++++++++++++++++++++++++++
 find/tree.c   |  1 +
 4 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/find/defs.h b/find/defs.h
index 52e522f..66e2648 100644
--- a/find/defs.h
+++ b/find/defs.h
@@ -464,6 +464,7 @@ PREDICATEFUNCTION pred_readable;
 PREDICATEFUNCTION pred_regex;
 PREDICATEFUNCTION pred_samefile;
 PREDICATEFUNCTION pred_size;
+PREDICATEFUNCTION pred_filesize;
 PREDICATEFUNCTION pred_true;
 PREDICATEFUNCTION pred_type;
 PREDICATEFUNCTION pred_uid;
diff --git a/find/parser.c b/find/parser.c
index 3ed5c31..e1e5800 100644
--- a/find/parser.c
+++ b/find/parser.c
@@ -138,6 +138,7 @@ static bool parse_regex         (const struct parser_table*, char argv[], int
 static bool parse_regextype     (const struct parser_table*, char *argv[], int *arg_ptr);
 static bool parse_samefile      (const struct parser_table*, char *argv[], int *arg_ptr);
 static bool parse_size          (const struct parser_table*, char *argv[], int *arg_ptr);
+static bool parse_filesize      (const struct parser_table*, char *argv[], int *arg_ptr);
 static bool parse_time          (const struct parser_table*, char *argv[], int *arg_ptr);
 static bool parse_true          (const struct parser_table*, char *argv[], int *arg_ptr);
 static bool parse_type          (const struct parser_table*, char *argv[], int *arg_ptr);
@@ -303,6 +304,7 @@ static struct parser_table const parse_table[] =
   PARSE_OPTION     ("show-control-chars",    show_control_chars), /* GNU, 4.3.0+ */
 #endif
   PARSE_TEST       ("size",                  size), /* POSIX */
+  PARSE_TEST       ("filesize",              filesize), /* GNU */
   PARSE_TEST       ("type",                  type), /* POSIX */
   PARSE_TEST       ("uid",                   uid),      /* GNU */
   PARSE_TEST       ("used",                  used),      /* GNU */
@@ -2129,7 +2131,7 @@ parse_size (const struct parser_table* entry, char **argv, int *arg_ptr)
 
   len = strlen (arg);
   if (len == 0)
-    error (EXIT_FAILURE, 0, _("invalid null argument to -size"));
+    error (EXIT_FAILURE, 0, _("invalid null argument to %s"), argv[*arg_ptr - 1]);
 
   suffix = arg[len - 1];
   switch (suffix)
@@ -2179,7 +2181,7 @@ parse_size (const struct parser_table* entry, char **argv, int *arg_ptr)
 
     default:
       error (EXIT_FAILURE, 0,
-      _("invalid -size type `%c'"), argv[*arg_ptr][len - 1]);
+      _("invalid %s type `%c'"), argv[*arg_ptr - 1], argv[*arg_ptr][len - 1]);
     }
   /* TODO: accept fractional megabytes etc. ? */
   if (!get_num (arg, &num, &c_type))
@@ -2189,8 +2191,8 @@ parse_size (const struct parser_table* entry, char **argv, int *arg_ptr)
       tail[1] = 0;
 
       error (EXIT_FAILURE, 0,
-      _("Invalid argument `%s%s' to -size"),
-      arg, tail);
+      _("Invalid argument `%s%s' to %s"),
+      arg, tail, argv[*arg_ptr - 1]);
       return false;
     }
   our_pred = insert_primary (entry, arg);
@@ -2211,6 +2213,11 @@ parse_size (const struct parser_table* entry, char **argv, int *arg_ptr)
   return true;
 }
 
+static bool
+parse_filesize (const struct parser_table* entry, char **argv, int *arg_ptr)
+{
+  return parse_size (entry, argv, arg_ptr);
+}
 
 static bool
 parse_samefile (const struct parser_table* entry, char **argv, int *arg_ptr)
diff --git a/find/pred.c b/find/pred.c
index f7e9b59..f4a4636 100644
--- a/find/pred.c
+++ b/find/pred.c
@@ -128,6 +128,7 @@ struct pred_assoc pred_table[] =
   {pred_regex, "regex   "},
   {pred_samefile,"samefile "},
   {pred_size, "size    "},
+  {pred_filesize, "filesize    "},
   {pred_true, "true    "},
   {pred_type, "type    "},
   {pred_uid, "uid     "},
@@ -979,6 +980,33 @@ pred_size (const char *pathname, struct stat *stat_buf, struct predicate *pred_p
 }
 
 bool
+pred_filesize (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
+{
+  uintmax_t f_val;
+
+  (void) pathname;
+  f_val = (stat_buf->st_size / pred_ptr->args.size.blocksize);
+  if (f_val == pred_ptr->args.size.size)
+      f_val = f_val + (stat_buf->st_size % pred_ptr->args.size.blocksize != 0);
+  switch (pred_ptr->args.size.kind)
+    {
+    case COMP_GT:
+      if (f_val > pred_ptr->args.size.size)
+ return (true);
+      break;
+    case COMP_LT:
+      if (f_val < pred_ptr->args.size.size)
+ return (true);
+      break;
+    case COMP_EQ:
+      if (f_val == pred_ptr->args.size.size)
+ return (true);
+      break;
+    }
+  return (false);
+}
+
+bool
 pred_samefile (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
 {
   /* Potential optimisation: because of the loop protection, we always
diff --git a/find/tree.c b/find/tree.c
index 2bbfbe5..e404721 100644
--- a/find/tree.c
+++ b/find/tree.c
@@ -980,6 +980,7 @@ static struct pred_cost_lookup costlookup[] =
     { pred_regex     ,  NeedsNothing         },
     { pred_samefile  ,  NeedsStatInfo        },
     { pred_size      ,  NeedsStatInfo        },
+    { pred_filesize  ,  NeedsStatInfo        },
     { pred_true      ,  NeedsNothing         },
     { pred_type      ,  NeedsType            },
     { pred_uid       ,  NeedsStatInfo        },
--
2.8.1

From 44c5e3486d2948e4a24070a7eec323ddc20d8d70 Mon Sep 17 00:00:00 2001
From: Tino Calancha <tino.calancha@gmail.com>
Date: Fri, 8 Jul 2016 14:58:04 +0900
Subject: [PATCH 3/4] * doc/find.texi (2.4 size): Document predicate filesize

---
 doc/find.texi | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/doc/find.texi b/doc/find.texi
index b3c5d10..812369a 100644
--- a/doc/find.texi
+++ b/doc/find.texi
@@ -1037,8 +1037,9 @@ indicates that the test should succeed if the file uses less than
 @var{n} units of storage.  Bear in mind that the size is rounded up to
 the next unit. Therefore @samp{-size -1M} is not equivalent to
 @samp{-size -1048576c}. The former only matches empty files, the latter
-matches files from 1 to 1,048,575 bytes.  There is no `=' prefix, because
-that's the default anyway.
+matches files from 1 to 1,048,575 bytes.  If you prefer that the size
+not be rounded you may want to use predicate @samp{-filesize}.
+There is no `=' prefix, because that's the default anyway.
 
 The size does not count indirect blocks, but it does count blocks in
 sparse files that are not actually allocated.  In other words, it's
@@ -1048,6 +1049,10 @@ and @samp{%b} format specifiers for the @samp{-printf} predicate.
 
 @end deffn
 
+@deffn Test -filesize n@r{[}bckwMG@r{]}
+Same as test @samp{-size} but the size is not rounded up to the next unit.
+@end deffn
+
 @deffn Test -empty
 True if the file is empty and is either a regular file or a directory.
 This might help determine good candidates for deletion.  This test is
--
2.8.1

From f8d116b8f652ef4b806f2bcd798cf7be9ba49d35 Mon Sep 17 00:00:00 2001
From: Tino Calancha <tino.calancha@gmail.com>
Date: Fri, 8 Jul 2016 15:31:25 +0900
Subject: [PATCH 4/4] Predicate blocksize alias to predicate size

  • find/defs.h: New predicate blocksize; alias to predicate size

(Bug #12162).

  • find/parser.c: Idem.
  • find/pred.c: Idem.
  • find/tree.c: Idem.


  • doc/find.texi (2.4 size): Document predicate blocksize; mention

that filesize is a GNU extension.
---
 doc/find.texi | 5 +++++
 find/defs.h   | 1 +
 find/parser.c | 8 ++++++++
 find/pred.c   | 7 +++++++
 find/tree.c   | 1 +
 5 files changed, 22 insertions(+)

diff --git a/doc/find.texi b/doc/find.texi
index 812369a..281ba70 100644
--- a/doc/find.texi
+++ b/doc/find.texi
@@ -1049,8 +1049,13 @@ and @samp{%b} format specifiers for the @samp{-printf} predicate.
 
 @end deffn
 
+@deffn Test -blocksize n@r{[}bckwMG@r{]}
+Same as test @samp{-size}, but not POSIX compliant.
+@end deffn
+
 @deffn Test -filesize n@r{[}bckwMG@r{]}
 Same as test @samp{-size} but the size is not rounded up to the next unit.
+This is a GNU extension.
 @end deffn
 
 @deffn Test -empty
diff --git a/find/defs.h b/find/defs.h
index 66e2648..a850c79 100644
--- a/find/defs.h
+++ b/find/defs.h
@@ -464,6 +464,7 @@ PREDICATEFUNCTION pred_readable;
 PREDICATEFUNCTION pred_regex;
 PREDICATEFUNCTION pred_samefile;
 PREDICATEFUNCTION pred_size;
+PREDICATEFUNCTION pred_blocksize;
 PREDICATEFUNCTION pred_filesize;
 PREDICATEFUNCTION pred_true;
 PREDICATEFUNCTION pred_type;
diff --git a/find/parser.c b/find/parser.c
index e1e5800..b186bc8 100644
--- a/find/parser.c
+++ b/find/parser.c
@@ -138,6 +138,7 @@ static bool parse_regex         (const struct parser_table*, char argv[], int
 static bool parse_regextype     (const struct parser_table*, char *argv[], int *arg_ptr);
 static bool parse_samefile      (const struct parser_table*, char *argv[], int *arg_ptr);
 static bool parse_size          (const struct parser_table*, char *argv[], int *arg_ptr);
+static bool parse_blocksize     (const struct parser_table*, char *argv[], int *arg_ptr);
 static bool parse_filesize      (const struct parser_table*, char *argv[], int *arg_ptr);
 static bool parse_time          (const struct parser_table*, char *argv[], int *arg_ptr);
 static bool parse_true          (const struct parser_table*, char *argv[], int *arg_ptr);
@@ -304,6 +305,7 @@ static struct parser_table const parse_table[] =
   PARSE_OPTION     ("show-control-chars",    show_control_chars), /* GNU, 4.3.0+ */
 #endif
   PARSE_TEST       ("size",                  size), /* POSIX */
+  PARSE_TEST       ("blocksize",             blocksize), /* GNU */
   PARSE_TEST       ("filesize",              filesize), /* GNU */
   PARSE_TEST       ("type",                  type), /* POSIX */
   PARSE_TEST       ("uid",                   uid),      /* GNU */
@@ -2214,6 +2216,12 @@ parse_size (const struct parser_table* entry, char **argv, int *arg_ptr)
 }
 
 static bool
+parse_blocksize (const struct parser_table* entry, char **argv, int *arg_ptr)
+{
+  return parse_size (entry, argv, arg_ptr);
+}
+
+static bool
 parse_filesize (const struct parser_table* entry, char **argv, int *arg_ptr)
 {
   return parse_size (entry, argv, arg_ptr);
diff --git a/find/pred.c b/find/pred.c
index f4a4636..32a2281 100644
--- a/find/pred.c
+++ b/find/pred.c
@@ -128,6 +128,7 @@ struct pred_assoc pred_table[] =
   {pred_regex, "regex   "},
   {pred_samefile,"samefile "},
   {pred_size, "size    "},
+  {pred_blocksize, "blocksize    "},
   {pred_filesize, "filesize    "},
   {pred_true, "true    "},
   {pred_type, "type    "},
@@ -980,6 +981,12 @@ pred_size (const char *pathname, struct stat *stat_buf, struct predicate *pred_p
 }
 
 bool
+pred_blocksize (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
+{
+  return pred_size (pathname, stat_buf, pred_ptr);
+}
+
+bool
 pred_filesize (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
 {
   uintmax_t f_val;
diff --git a/find/tree.c b/find/tree.c
index e404721..c5d2ee4 100644
--- a/find/tree.c
+++ b/find/tree.c
@@ -980,6 +980,7 @@ static struct pred_cost_lookup costlookup[] =
     { pred_regex     ,  NeedsNothing         },
     { pred_samefile  ,  NeedsStatInfo        },
     { pred_size      ,  NeedsStatInfo        },
+    { pred_blocksize ,  NeedsStatInfo        },
     { pred_filesize  ,  NeedsStatInfo        },
     { pred_true      ,  NeedsNothing         },
     { pred_type      ,  NeedsType            },
--
2.8.1


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

find (GNU findutils) 4.7.0-git
Repository revision: 155c9d1c229aa5d12b6e8919516fd6331a28ba1e

Tino Calancha <calancha>
Thu 26 May 2016 08:06:24 AM UTC, comment #30: 

Tino, I am totally happy with -filesize option suggestion, yet, it would be important to also have comparing bigger, smaller or equal. How would you solve this?

I suggest:

-size lt 1M: less than one MiB (< 1048576 bytes, 1048575 matches 1048576 does not match)
-size lte 1M: less than or equal one MiB (<= 1048576 bytes)
-size gt 1M: more than one MiB (> 1048576 bytes)
-size gte 1M: more or equal than one MiB (>= 1048576 bytes)
-size eq 1M: exactly one MiB (=1048576 bytes)

as I wrote in comment #24. It would theoretically even allow to keep the option name "-size". But I am also fine with changing it to "-filesize". I just wonder, to make it consistent for times as well we would need new option names for time as well. I think it is easy enough to detect "lt/lte/gt/gte/eq" with the existing option names reliably.

Bonus points for allowing decimal versus binary notations as well, so maybe MB versus MiB?

Martin Steigerwald <martin21>
Thu 26 May 2016 04:01:44 AM UTC, comment #29: 

Hi,

i am one of those people missing a find size predicate
without rounding.
IMHO Nigel's suggestion (comment #16) is very elegant:

I)  It preserves backward compatibility.
II) It provides the missing feature (size predicate without rounding).

(So every people would be happy).

Note for maintainers:
In case you like Nigel's solution but you lack of man power to
implement it, please let me know: I am willing to work on it.

Tino Calancha <calancha>
Wed 15 Aug 2012 05:32:13 PM UTC, comment #28: 

James, sure, would get to convoluted here otherwise. I reported the time stuff as bug #37110 find: alternative time handling. I think its important to keep times somewhere in mind in order to be able to find a solution that work consistently between sizes and times. Thanks, Martin

Martin Steigerwald <martin21>
Wed 15 Aug 2012 03:36:15 PM UTC, comment #27: 

Could we discuss time handling in a separate bug please?

James Youngman <jay>
Group administrator
Wed 15 Aug 2012 03:05:03 PM UTC, comment #26: 

-[a|c|m]time eq 1d makes no sense with nanosecond precision cause it hits extremely rarely. I´d skip -eq for times. Searching exact filesizes make more sense.

-[a|c|n]time eq "exact absolute time spec" makes more sense, cause search for an exact time doesn't seem to be possible at all at the moment as -[c|a|]newer goes with more or less (with !) but not equal

An option for timespec to limit resolution may be good to not have to type in the exact nanosecond timestamp.


Martin Steigerwald <msteamix>
Wed 15 Aug 2012 02:49:44 PM UTC, comment #25: 

Updated time results for consistency comparison:

ms@mango:/tmp/find-times> ls -l                                    
insgesamt 0
-rw-rw-r-- 1 ms teamix 0 Aug 14 18:11 lessthan1dayago
-rw-rw-r-- 1 ms teamix 0 Aug 13 18:12 lessthan2daysago
-rw-rw-r-- 1 ms teamix 0 Aug 12 18:12 lessthan3daysago
-rw-rw-r-- 1 ms teamix 0 Aug 14 16:11 morethan1dayago
-rw-rw-r-- 1 ms teamix 0 Aug 13 16:11 morethan2daysago
-rw-rw-r-- 1 ms teamix 0 Aug 12 16:11 morethan3daysago
ms@mango:/tmp/find-times> date
Mi 15. Aug 16:29:51 CEST 2012
ms@mango:/tmp/find-times> find -mtime +1  -printf "%p\t %t\n" | sort
./lessthan3daysago       Sun Aug 12 18:12:10.0626806028 2012
./morethan2daysago       Mon Aug 13 16:11:42.0727680142 2012
./morethan3daysago       Sun Aug 12 16:11:50.0715653807 2012

As predicted -mtime +1 translated to more than two days ago.

ms@mango:/tmp/find-times> find -mtime +3  -printf "%p\t %t\n" | sort

+3 translates to more than 4 days ago, thus no results

ms@mango:/tmp/find-times> find -mtime +2  -printf "%p\t %t\n" | sort
./morethan3daysago       Sun Aug 12 16:11:50.0715653807 2012

And +2 to more than 3 days ago.

Yet with -time it seems to be the other way around:

ms@mango:/tmp/find-times> find -mtime -2  -printf "%p\t %t\n" | sort
./lessthan1dayago        Tue Aug 14 18:11:33.0444291877 2012
./lessthan2daysago       Mon Aug 13 18:12:00.0302854716 2012
./morethan1dayago        Tue Aug 14 16:11:23.0258103147 2012
.        Wed Aug 15 16:12:10.0625203012 2012

-2 translates to less than 2 days ago (as I actually wrote before)

ms@mango:/tmp/find-times> find -mtime -1  -printf "%p\t %t\n" | sort
./lessthan1dayago        Tue Aug 14 18:11:33.0444291877 2012
.        Wed Aug 15 16:12:10.0625203012 2012

-1 to less than one day ago.

Thus we have:

-mtime -1: less than one day
-mtime 1: one day, 24-48 or <48 hours
-mtime +1: more than two days!

And:

-size -1M: 0 MBytes = 0 bytes
-size -2M: less or equal than 1 MiB!
-size +1M: more than 1 MiB

I'd suggest:

-size lt 1M: less than one MiB (< 1048576 bytes, 1048575 matches 1048576 does not match)
-size lte 1M: less than or equal one MiB (<= 1048576 bytes)
-size gt 1M: more than one MiB (> 1048576 bytes)
-size gte 1M: more or equal than one MiB (>= 1048576 bytes)
-size eq 1M: exactly one MiB (=1048576 bytes)

And for completeness for times as well:

-mtime lt 1d: less than one day (00:00:00 to 23:59:59.9999999999999, short < 24:00:00)
-mtime lte 1d: less or equal one day (00:00:00 to 24:00:00)
-mtime gt 1d: more than one day (24:00:00.0000000000001, short >24:00:00 to anything)
-mtime gte 1d: more or equal one day (24:00:00 to anything)
maybe -mtime eq 1d: exactly one day (24:00:00.000000000000)

Old semantic for -mtime 1 can be more clearly expressed by:

-mtime gte 1d -and -mtime lt 2d


Advantages:
1) a lot more intuitive to human beings

2) distinction between < and <= as well as > and >=

3) compatible with old scripts, cause old behavior can be kept (I actually teach the -[a|c|m]time wierdness since quite some time)

4) no conflict with input/output redirection

5) different units possible for times as well (d = days, h = hours, m=minutes, M=months, Y=years and such or even have it verbose to reduce ambiquity)

I am not so sure about the usefulness / semantics of the "eq" case, especially for times. For sizes it might make more sense. But then exactly matching a time could be useful.

I happily put the time stuff in an extra report and link to it from here. But I thought the comparison with time handling makes the inconsistency in find behaviour from the viewpoint of human beings even more obvious.

The current handling of -size / -[a|c|m]time IMHO is well suited for machines (integer math with any, even big units), but not for humans.

What do you think?

Martin

Martin Steigerwald <msteamix>
Wed 15 Aug 2012 02:24:43 PM UTC, comment #24: 

Forget the time results. touch sets access and modification time, not status change time. I test again with mtime.

Martin Steigerwald <msteamix>
Wed 15 Aug 2012 02:20:32 PM UTC, comment #23: 

I have:

mango:/tmp# find -name "nullen*" -printf "%p %s\n" | sort
./nullen0999 1022976
./nullen1000 1024000
./nullen1001 1025024
./nullen1024 1048576
./nullen1025 1049600
./nullen2047 2096128
./nullen2048 2097152
./nullen2049 2098176

Yet while

mango:/tmp# find -size +1M -size -3M -printf "%p %s\n" | sort
./nullen1025 1049600
./nullen2047 2096128
./nullen2048 2097152

Does not show up nullen2049 cause find rounds -3M to next integer unit <=2M. Yet find doesn't round up +1M to >=2M. I think this behavior is quite unpredictable and inconsistent.

Especially as -[a|m|c]mtime exactly behaves that way even for "+" – well at least in my last test it did.

But unless I am grossly off track this doesn't work at all ATM:

ms@mango:/tmp/find-times> touch -d "1 day ago" morethan1dayago
ms@mango:/tmp/find-times> touch -d "22 hours ago" lessthan1dayago
ms@mango:/tmp/find-times> touch -d "2 days ago" morethan2daysago
ms@mango:/tmp/find-times> touch -d "3 days ago" morethan3daysago
ms@mango:/tmp/find-times> touch -d "46 hours ago" lessthan2daysago
ms@mango:/tmp/find-times> touch -d "70 hours ago" lessthan3daysago

ms@mango:/tmp/find-times#2> ls -l --time=ctime
insgesamt 0
-rw-rw-r-- 1 ms teamix 0 Aug 15 16:11 lessthan1dayago
-rw-rw-r-- 1 ms teamix 0 Aug 15 16:12 lessthan2daysago
-rw-rw-r-- 1 ms teamix 0 Aug 15 16:12 lessthan3daysago
-rw-rw-r-- 1 ms teamix 0 Aug 15 16:11 morethan1dayago
-rw-rw-r-- 1 ms teamix 0 Aug 15 16:11 morethan2daysago
-rw-rw-r-- 1 ms teamix 0 Aug 15 16:11 morethan3daysago

ms@mango:/tmp/find-times> date
Mi 15. Aug 16:16:26 CEST 2012

ms@mango:/tmp/find-times> find -ctime -2 -printf "%p\t %c\n" | sort
./lessthan1dayago        Wed Aug 15 16:11:33.0439805365 2012
./lessthan2daysago       Wed Aug 15 16:12:00.0298369109 2012
./lessthan3daysago       Wed Aug 15 16:12:10.0625203012 2012
./morethan1dayago        Wed Aug 15 16:11:23.0256899464 2012
./morethan2daysago       Wed Aug 15 16:11:42.0723161276 2012
./morethan3daysago       Wed Aug 15 16:11:50.0711165207 2012
.        Wed Aug 15 16:12:10.0625203012 2012

Note how find display day as 15 August on every file. find -ls shows correct results.

Hmmm, but thats a different bug it seems, that I will report in a moment.

Still last I checked with -exec ls -ld {} \; -ctime behaved as follows:

- ctime 1: 24-48 hours earlier
- ctime -1: 0-24 hours earlier
- ctime +1: >=48 (!) hours earlier

So I suggest new time options as well. I'd like the aliasing idea with -size => -blocksize.

Or maybe "gt" and "lt" could serve for new fractional comparing? Like in "test" command. But thats > and <, not <= and =>. I think the semantics which one find uses should also be clarified.

Martin Steigerwald <msteamix>
Sun 27 May 2012 09:49:48 PM UTC, comment #22: 

I'd just like to cast another vote for the view that the behavior of the -size flag is incorrect.  Though I have read and understood the arguments in favor of maintaining the current behavior, I don't see any way around the following dilemma.  Either:

1) -size is broken because of the rounding behavior, or

2) -size correctly implements a different search criterion (i.e. size by blocks), and therefore find lacks a flag for search by  file size. 

Although I would be mildly surprised to learn that anyone has written code which relies on the rounding behavior, there's surely no harm in adding another flag, (e.g. -filesize as Jay Youngman suggested) which has the semantics that 99.9% of users expect?

I find myself in sympathy with xeo's incredulity that a behavior that has bitten this many people since (at least) 2005 has not been remedied by any of the Pareto-optimal, compatability-preserving means available, like adding another flag that does the right thing.  Can I ask what would constitute sufficient evidence that fixing this behavior (or remedying it with another flag) would be endorsed by the community? 

Best regards,
Patrick.

Patrick O'Neill <poneill>
Thu 05 Aug 2010 10:28:21 AM UTC, comment #21: 

Hello all,

I currently stumbled over the "feature", that filesizes are obviously rounded up before comparing.

So, I wanted to find all files smaller than 1MB and I - naivly - assumed that a

find . -type f -size -1M

would do the job, but instead of returning me every file less than 1MB, it gave me all files with exactly 0Byte back.

Apparently, -1MB means "less than 1MB" which means 0MB and everything rounded up which is >0Byte is 1MB, so there was no hit at all.

I thought, this would be a bug but surprisingly the community is aware of it and hasn't done something to fix it (the last 25yrs?) - so it has to be a feature.

Wouldn't it be possible to fix this behaviour?

I realized, this thread is 5 years old and I can't believe this topic is sooo difficult that there is absolutely no agreement possible ;-)

I agree with Peter Splichal, who suggested "--1MB" for disabling rounding up ...

Best Regards,
Xeo

Thomas P <xeo>
Mon 12 Apr 2010 12:17:50 AM UTC, comment #20: 

Just call it filesize. Sure, it might not apply to just files, but that's the name everyone will be looking for.

Nigel McNie <nigel>
Sun 11 Apr 2010 10:10:32 PM UTC, comment #19: 

I like Nigel's suggestion of -filesize. 

i suggest adding "c" as a synonym for "b." 

I further suggest that all the units be made case-insensitive.

I like Nigel's further suggestion about -size and -blocksize.  Also, print a warning to stderr if the user uses "-size" with any unit other than "c". 

Thanks for thinking about this.

dan pritts <danpritts>
Sun 11 Apr 2010 07:17:22 PM UTC, comment #18: 

Ole is right; the <, > method won't work well.  But we seem to have overlooked the idea of creating a new predicate which is similar to -size but does no rounding. 

Any preferences for what we should call the test?

-exactsize
-length
-size.norounding
-size-norounding
-size unrounded -1G
...?

James Youngman <jay>
Group administrator
Thu 12 Nov 2009 08:38:21 PM UTC, comment #17: 

I ran into this bug today. Having read the comments, may I make a suggestion: Add a -filesize option, which works the way everyone clearly expects.

-filesize n[bkMGTP]
        File uses n bytes of space. The following suffixes can be used:
        'b'    for bytes
        'k'    for Kilobytes (1024 bytes)
        'M'    for Megabytes (1048576 bytes)
        'G'    for Gigabytes (1073741824 bytes)
        'T'    for Terabytes (...)
        'P'    for Petabytes (...)

For bonus points: add -blocksize, alias -size to -blocksize (so people reading the manpage can tell the difference between the two easily), and change the wording for the help -blocksize to refer to blocks to make it obvious that people don't want to do that when they want -filesize.

This preserves backward compatibility, while making 'find' a whole bunch more useful.

Nigel McNie <nigel>
Wed 11 Mar 2009 03:15:04 PM UTC, comment #16: 

If my daughter's Rottweiler weighs more pounds than she, then changing
the units to metric (kilograms) does not imply she has suddenly put on
weight and now magically weighs the same as her dog.

If her 3 foot 8 inches seems small, when compared with the height of a
skyscraper, she nevertheless remains small by comparison even when the
units are changed from inches to lightyears.

It seems to me that the fundamental problem here is with the ambiguity
of "units".  The maintainer evidently -- and rightly so -- perfers the
simplicity, utility, and consistency of the current implementation.  I
believe that is justified, given that "units" refers to "granularity".

If the precision of measurement is so extremely coarse-grained as to
prevent a distinction in height between my daughter and Mount Everest,
it may be reasonable to deem their heights the same.  The problem with
the find command is... well... there is no problem; there is a problem
with the documentation however.  The documentation should explicitly
point out how "units" refers to granularity, to how coarse-grained
the measurements are.  Moreover the succinct clarification provided by
Andreas Metzler should -- in my opinion -- be in the documentation.

vose <vose>
Tue 10 Mar 2009 08:36:02 PM UTC, comment #15: 

I don't believe the behavior is correct, but here's the line of reasoning.

THe original find implementation counts disk blocks.  A block is either used (partially or fully), or not.

Blocks are (typically?  always?) 512 bytes long. 

You are looking for blocks that are used, and therefore cannot be used by other files, which is the key distinction why this makes sense for blocks but not for megabytes or whatever.

So if you search for size -2, you are not really searching for anything that is using less than 1024 bytes, you are searching for something that is using 1 full block, and no portion of a second block. 

If you apply the same logic to a different unit, gigabytes, you will end up with the situation where a file of 1 gigabyte + 1 byte is using a portion of the second gigabyte, therefore the test fails.

This is obviously the wrong logic to use when units are something other than disk blocks, but that's how it got this way.

The maintainer suggests in the comments below that changing this might break backward compatibility.  Let's just say that I strongly disagree.

dan pritts <danpritts>
Tue 10 Mar 2009 06:13:42 PM UTC, comment #14: 

"Would someone please explain -- completely and carefully -- just
exactly how find's behavior is actually correct?"

Step one: How many 1M blocks does the 3200 byte file take? Answer: one. (Clearly it cannot be zero.)
Step two: Is one stricly lower than 1? No it is not.
Test failed.

Andreas Metzler <ametzler>
Tue 10 Mar 2009 04:50:21 PM UTC, comment #13: 

As near as I can tell, find is broken when it comes to -size.
It fails to realize that a 3200 byte file has a size which is
less than 1M, as evidenced by the failure of ... -size -1M ...

Reading comments here leads me to believe: whereas other people
are likewise confused, nevertheless somehow the behavior of
find is thought in some sense to be correct.

Would someone please explain -- completely and carefully -- just
exactly how find's behavior is actually correct?  It does not
seem to me that the man page (or info) adequately explains this
subtlety.

Thanks in advance.

vose <vose>
Tue 14 Oct 2008 01:23:44 PM UTC, comment #12: 

I see the "logic" of units, but this really isn't very
intuitive behaviour, which is confirmed by the fact
that more and more people run into this issue. Today it
was me:

https://bugzilla.redhat.com/show_bug.cgi?id=466462

I think the best solution now really is to provide an
alternative modifier for size parameter (not to break
backward compatibility) as has been already mentioned
in previous comments.

As we do not have a big choice as far as available
chars are concerned, we should choose better something
than nothing. I vote for using -- and ++ which do not
have to be escaped and (hopefully) will not break the
findutils' test suite.

++ and -- does not seem that bad after all...

find -size --1M
find -size ++1M

the only other that I can think of are _ and ^

find -size _1M
find -size ^1M

but I don't like them much...

If the testsuite could be modified so that < and > are
acceptable, I would probably vote for them because of
their clear meaning (despite they have to be escaped).

Petr Splichal <psss>
Mon 18 Aug 2008 10:16:20 PM UTC, comment #11: 

While I was at it I checked Solaris 10.

Their find command does not have any units other than blocks & characters. 

The -size N behaves like gnu find, ie, 513-byte files are not shown if you ask for -size -2

-size -1024c, however, works like FreeBSD.

dan pritts <danpritts>
Mon 18 Aug 2008 10:11:37 PM UTC, comment #10: 

FreeBSD 7 find also works the way i'd want it to, and the man page  snippet is identical to the one from MacOS I quote below.

thanks for taking the time to think about this.

dan pritts <danpritts>
Mon 18 Aug 2008 04:13:19 PM UTC, comment #9: 

MacOS find behaves in the way i'd expect, at least in the obvious case of -size -1G;

It has this in the man page:

     -size n[ckMGTP]
             True if the file's size, rounded up, in 512-byte blocks is n.  If
             n is followed by a c, then the primary is true if the file's size
             is n bytes (characters).  Similarly if n is followed by a scale
             indicator then the file's size is compared to n scaled as:

             k       kilobytes (1024 bytes)
             M       megabytes (1024 kilobytes)
             G       gigabytes (1024 megabytes)
             T       terabytes (1024 gigabytes)
             P       petabytes (1024 terabytes)

I've asked a bsd-head friend for a login on his box and will report back what i find.

dan pritts <danpritts>
Sat 16 Aug 2008 08:10:16 AM UTC, comment #8: 

How about clarifying the documentation? I have been asked for this in Debian bug#489905. Patch attached.

Does anybody know how FreeBSD's find behaves?

(file #16299)

Andreas Metzler <ametzler>
Tue 12 Aug 2008 08:11:24 PM UTC, comment #7: 

Due to the nature of filesystem disk allocation and use of blocks,             
I guess i can imagine why someone who's searching on blocks would              
be sad if his block search showed him files that were using that               
many blocks, so the (undocumented?) rounding requirement may fit with the principle of least surprise.

For any other unit it seems horribly broken.  Maybe the right solution is to leave the rounding logic for searches on blocks, but do as anonymous in comment #3 suggests and make the k/M/G suffixes act as multiplers of "c".

dan pritts <danpritts>
Tue 12 Aug 2008 07:43:47 PM UTC, comment #6: 

I ran into this bug today.  The degenerate case was that "find -size -1G" only matches files zero bytes in size.  I am really having a hard time imagining who in their right mind would want this.

I find this behavior to be horribly broken.  Maybe this deserves to be a different bug but I'd put the severity at the highest level.

I think I understand what you're getting at w/r/t the "rounding requirement" but i don't see it documented in the info page anywhere.  the "info" program is user-hostile and I don't use emacs, so i suppose i may have not been able to find it, but i certainly found other uses of the word "rounding."

the documentation refers to "rounding" in the discussion of size, but only states that the sizes are rounded up ("true if the file uses N units of space, rounding up").

James, your comment reminds me of the old joke about "putting the backward in backward-compatible."

regarding the comment about < and > I agree that it would not be a good thing, users would be hosed by it.  -- and ++ don't really seem like very good alternatives either but I don't have any better suggestions.

dan pritts <danpritts>
  Spam posted by anonymous
Sat 17 Nov 2007 02:27:20 PM UTC, comment #4: 

Anonymous, the problem with your suggestion that "-size -2147483648c" and "-size -2G" should be completely identical is that it would be a backward-incompatibel change.

James Youngman <jay>
Group administrator
Sat 15 Sep 2007 04:14:36 PM UTC, comment #3: 

IMO the solution is obvious, the letters k,M,G,T,P,E,Z,Y are NOT units they are SI multipliers, they multiply the base unit which in this case is bytes. so the stanzas "-size -2147483648c" and "-size -2G" should be completely identical. I would suggest a suffix perhaps like "-size 2G/4k" so you can find all files that can be put on a filesystem with a blocksize of 4k and a max file size of just under 2GiB.

Anonymous
Thu 30 Aug 2007 03:25:16 PM UTC, comment #2: 

In general < and > are bound to cause problems for normal users. Could we use ++ and -- instead?

Ole Tange <tange>
Fri 04 Mar 2005 10:25:58 AM UTC, comment #1: 

I've written the attached patch which implements the feature but the way that the test suite works prevents us passing "<" or ">" as part of an argument to "find".  Hence we can't include test cases for this feature.  That being the case, I'm not going to apply the patch.   Maybe we can come up with some alternative syntax that avoids this problem.

James Youngman <jay>
Group administrator
Sun 27 Feb 2005 11:11:33 AM UTC, original submission:  

At the moment find . -size -2G will not find a file which is 1Gb in size, because of the rounding requirement (i.e. that find . -size -2 should not match a 750 byte file).  The same rounding up works for -size arguments where the multiplier is much larger.  The problem is that one would ordinarily assume that "-size -2G" would match a 1.5Gb file.  Hence perhaps we should introduce "-size <2G" which works the way the user might expect.

James Youngman <jay>
Group administrator

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

Attached Files
file #16299:  12162.diff added by ametzler (1KiB - text/x-diff - fix docs.)
file #2660:  find-4.2.19-CVS-sizerounding-sv12162.patch added by jay (6KiB - text/x-patch - -size rounding patch implementing the desired feature)

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by calancha (Posted a comment)
  • -email is unavailable- added by mikini
  • -email is unavailable- added by martin21 (Posted a comment)
  • -email is unavailable- added by martin21
  • -email is unavailable- added by msteamix (Posted a comment)
  • -email is unavailable- added by poneill (Posted a comment)
  • -email is unavailable- added by xeo (Posted a comment)
  • -email is unavailable- added by nigel (Posted a comment)
  • -email is unavailable- added by vose (Posted a comment)
  • -email is unavailable- added by psss (Posted a comment)
  • -email is unavailable- added by danpritts (Posted a comment)
  • -email is unavailable- added by jay (Posted a comment)
  • -email is unavailable- added by tange (Posted a comment)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only logged-in users can vote.

     

    Follow 9 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2015-11-19 mikini Carbon-Copy- Added mikini
    2012-08-15 martin21 Carbon-Copy- Added martin21
    2010-04-11 jay StatusNone Need Info
        SummaryEnhancement req: finding files less than 2Gb in size Enhancement req: finding files less than 2Gb in size [needs community feedback]
    2009-03-10 ametzler Carbon-CopyRemoved 20807 -
    2008-10-14 ametzler Carbon-CopyRemoved 20807 -
    2008-08-16 ametzler Attached File- Added 12162.diff, #16299
    2005-03-04 jay Attached File- Added find-4.2.19-CVS-sizerounding-sv12162.patch, #2269
    2005-02-27 jay Carbon-Copy- Added -email is unavailable-

    Back to the top

    Powered by Savane 3.13-f8d8.
    Corresponding source code