bugfindutils - Bugs: bug #62089, find -size -1024k different from...


bug #62089: find -size -1024k different from -size -1M

Submitter:  None
Submitted:  Mon 21 Feb 2022 02:12:06 AM UTC
Category:  find Severity:  3 - Normal
Item Group:  Wrong result Status:  None
Privacy:  Public Assigned to:  None
Originator Name:  Originator Email:  -email is unavailable-
Open/Closed:  Open Release:  4.7.0
Fixed Release:  None
* Mandatory Fields

Add a New Comment Rich Markup

Wed 23 Feb 2022 04:27:02 PM UTC, comment #3: 

That's an extension on the standard POSIX behaviour. c is the only suffix supported by POSIX find -size. Without suffix, the unit is 512 byte blocks (formerly commonly known as sectors).

-size n: matches on files whose size rounded up to the next integer number of 512 byte units is exactly n. For instance, -size 2 selects files with sizes 513 to 1024 bytes.

-size -n: when that number is strictly less than n. So with -size -2, that's files with sizes 0 to 512 bytes

-size +n: when that number is strictly more than n. So with -size +2, that's files with size of 1025 bytes or more.

GNU find extended it with more suffixes (kmg...) but with the same semantic. Same happens in zsh with its L glob qualifier: *(LM-2) matches on files with size 0 to 1048576.

FreeBSD find also added suffix support in 2006, but while it honours the POSIX rule for -size n without suffix, with suffixes, it uses the more intuitive semantic where -size 10M is the same as -size 10485760c.

I agree the GNU behaviour is more confusing and unintuitive, but it's too late now to change the semantic. It would mean not being standard compliant for suffix-less numbers and it would break backward compatibility (though it's likely it probably would also fix some scripts which expect the more intuitive behaviour)

What could be done is introduce new syntax with a different semantic. For instance, we could have -size '<=10MiB' to match on files that  are less than 10MiB. Or we could have a new -apparent-size '-10M' with the more intuitive API. I'll let the GNU find maintainers comment on whether they would consider doing it.

Note that there's a similar problem with -atime/-mtime... where -mtime +n matches on files whose age rounded down to the next integer number of days is strictly greater than n.  So for instance -mtime +1 matches on files that are over 2 days old, not one, because a file that is 47:59:59.999999 days old is rounded down to 1 day which is not strictly greater than 1.

Again, both GNU and FreeBSD find support suffixes as extension, but again with different semantics.

For those though, there is already a different (non-standard) API that we can use with a more intuitive API: ! -newermt '1 day ago' as a more intuitive equivalent to -mtime +0 (same as FreeBSD's -mtime +1d or +24h/+1440m/+86400s).

The -newermt was originally from BSD.

Stephane Chazelas <stephanechazelas>
Mon 21 Feb 2022 02:33:28 AM UTC, comment #2: 

I think I know why, in `man find`, it actually gives an example:

       -size n[cwbkMG]


The + and - prefixes signify greater than and less than, as usual; i.e., an exact size of n units does not match.  Bear in mind that the size is rounded up  to  the
              next unit.  Therefore -size -1M is not equivalent to -size -1048576c.  The former only matches empty files, the latter matches files from 0 to 1,048,575 bytes.


So it "only matches empty files"! this behavior is so confusing!

Can we change to let 1M means 1,048,575 bytes? or at least issue a warning: saying "this flag only matches empty files"!.

Mon 21 Feb 2022 02:14:44 AM UTC, comment #1: 
Mon 21 Feb 2022 02:12:06 AM UTC, original submission:  

I'm trying to count the image files by size, here is what I got:

find -size -1024k  different from -size -1M

$ find data/images/ -type f -name '*.jpg' | wc
 878161  878161 27220516  # total number of jpg files

$ find data/images/ -type f -name '*.jpg'  -size -500k | wc
 878065  878065 27217540  # number of files whose size < 500k

$ find data/images/ -type f -name '*.jpg'  -size -1M | wc
    356     356   11036   # number of files whose size < 1M

So how come it's only 356 (much less than 878065)?

Anyone can explain? or tell me what's going wrong?

Then I tried `-1024k`, instead of `-1M`, which returns reasonable number:
$ find data/images/ -type f -name '*.jpg'  -size -1024k | wc
 878119  878119 27219214

So, why `-1M` behaved so wrong?

Below is my machine's system info:

$ which find

$ dpkg -S /usr/bin/find
findutils: /usr/bin/find

$ dpkg -l findutils
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                                    Version                  Architecture             Description
ii  findutils                               4.6.0+git+20170828-2     amd64                    utilities for finding files--find, xargs

$ find --version
find (GNU findutils) 4.7.0-git
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Eric B. Decker, James Youngman, and Kevin Dalley.
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION FTS(FTS_CWDFD) CBO(level=2)

$ cat /etc/issue.net
Ubuntu 18.04.2 LTS

$ uname -a
Linux 4.15.0-55-generic #60-Ubuntu SMP Tue Jul 2 18:22:20 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux



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

Attach Files:

No files currently attached


Depends on the following items: None found

Items that depend on this one: None found


Carbon-Copy List
  • -email is unavailable- added by stephanechazelas (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.


    No changes have been made to this item

    Back to the top

    Powered by Savane 3.13-4b48.
    Corresponding source code