Subject: bug#17553: du unit suggestion

From: Pádraig Brady <[email-masked]>
Date: Fri, 23 May 2014 13:12:29 +0100

tl;dr

  You can get what you want currently by doing:

    du() { env du -B1 "$@" | numfmt --to=iec-i --suffix=B; }

  Though there are some potential changes.
  I'm 60:40 against applying the attached block-size-iec-iB.patch
  I'm 60:40 for applying the attached block-size-help-iB.patch

details below...

On 05/23/2014 11:13 AM, Reuben Thomas wrote:
> On 22 May 2014 23:58, Pádraig Brady <[email-masked]> wrote:
> 
>> On 05/22/2014 08:47 PM, Reuben Thomas wrote:
>>> It would be helpful to this addle-pated individual if du would output the
>>> same units as it accepts as SIZE inputs, so that one could more readily
>>> tell whether one was getting 1000-based or 1024-based units.
>>>
>>> For additional clarity, it would help if for output the suffix were "B"
>> as
>>> at present for 1000-based units and "iB" for 1024-based (and
>>> correspondingly it would be nice if "iB" suffixed units were accepted as
>>> input. As far as input goes, it's backwards-compatible; it's not for
>> output
>>> if other programs are trying to parse the human-readable output, but
>> maybe
>>> that's not a problem.
>>
>> Yes this is not ideal, but it half does what you want:
>> With this file:
>>
>>   $ truncate -s 1MiB file.in
>>
>> We can output the appropriate suffixes for a _particular_ power.
>>
>>   $ du --apparent-size -BKiB file.in
>>   1024KiB       file.in
>>   $ du --apparent-size -BKB file.in
>>   1049kB        file.in
>>
>> However if we want to auto scale the number with -h we lose the suffix,
>> and have an ambiguity:
>>
>>   $ du --apparent-size -h file.in
>>   1.0M  file.in
>>   $ du --apparent-size -h --si file.in
>>   1.1M  file.in
>>
>> If you wanted to get auto scaling with suffixes you could use
>> the new numfmt utility which has various number formatting options.
>> The advantage of that is it concentrates the myriad of number formatting
>> options in a single location, and allows processing of numbers before
>> final presentation by numfmt. For example:
>>
>>   $ du -B1 . | sort -k1,1n | numfmt --to=iec-i | tail -n5
>>   104Mi ./gnulib/.git/objects/pack
>>   216Mi ./gnulib/.git/objects
>>   218Mi ./gnulib/.git
>>   274Mi ./gnulib
>>   479Mi .
>>
> 
> Thanks for clarifying what is possible. Currently du's behaviour is more
> inconsistent than I'd realised. I see that if one wanted more complicated
> units it would make sense to use an external utility, but here I'd just
> like -h's output to be consistent with --apparent-size's output.

With -B '..B' output you mean?

To show all current output possibilities:

$ dd bs=1MiB count=2 if=/dev/zero of=file.test
$ for B in 1 1000 1024 KB KiB si human; do
    printf '%s (%s)\n' "$(du -B$B file.test)" "$B"
  done
2097152	file.test (1)
2098	file.test (1000)
2048	file.test (1024)
2098kB	file.test (KB)
2048KiB	file.test (KiB)
2.1M	file.test (si)
2.0M	file.test (human)

For backward compat I'm a bit reluctant to have -h (or -Bhuman)
without --si output the 'i' suffix. It is tempting though,
but another reason not to do this, is the current implementation
would also output the 'B' suffix, which might be OK for du,
but we also need to consider ls and df where this is also significant.

I guess we could extend the --block-size option to support this
(simple patch is attached)

$ for B in iec-iB si-B; do printf '%s (%s)\n' "$(src/du -B$B file.test)" "$B"; done
2.0MiB	file.test (iec-iB)
2.1MB	file.test (si-B)

However as mentioned the current implementation of this doesn't support
outputting the 'i' iec distinguishing char without the 'B' suffix.
Also given the messiness in this area I'm reluctant to add to it.
numfmt gives all the flexibility you need here and you can setup:

  du() { env du -B1 "$@" | numfmt --to=iec-i --suffix=B; }

That would be more general and just about as awkward as:

  alias du='du -Biec-iB'

> It seems that -iB suffixed units are already accepted as input, which was
> my second request, but not documented in the man page. I'd like to fix
> this, but without duplicating information. What's best: to add a phrase
> saying that SI units are accepted and/or to make a cross-reference to the
> relevant node of the info manual?

Yes the man page doesn't mention that the integer is optional and
the consequences of that, nor does it mention the 'human' and 'si' possibilities.
Man pages are a tricky to have the right level of info.
BTW having the integer optional was removed from the description in:
  http://debbugs.gnu.org/cgi/bugreport.cgi?bug=9939#53
I've attached a proposed patch to show the -B'MiB' as an option,
while leaving the SIZE description as before.

thanks,
Pádraig.
diff --git a/lib/human.c b/lib/human.c
index ab6b30d..d5d5a79 100644
--- a/lib/human.c
+++ b/lib/human.c
@@ -394,11 +394,20 @@ human_readable (uintmax_t n, char *buf, int opts,
 # define DEFAULT_BLOCK_SIZE 1024
 #endif
 
-static char const *const block_size_args[] = { "human-readable", "si", 0 };
+static char const *const block_size_args[] =
+  {
+    "human-readable",
+    "iec-iB",
+    "si",
+    "si-B",
+    0 };
+
 static int const block_size_opts[] =
   {
     human_autoscale + human_SI + human_base_1024,
-    human_autoscale + human_SI
+    human_autoscale + human_SI + human_base_1024 + human_B,
+    human_autoscale + human_SI,
+    human_autoscale + human_SI + human_B
   };
 
 static uintmax_t
diff --git a/src/df.c b/src/df.c
index 01ecca6..8941632 100644
--- a/src/df.c
+++ b/src/df.c
@@ -1276,7 +1276,7 @@ or all file systems by default.\n\
       fputs (_("\
   -a, --all             include dummy file systems\n\
   -B, --block-size=SIZE  scale sizes by SIZE before printing them; e.g.,\n\
-                           '-BM' prints sizes in units of 1,048,576 bytes;\n\
+                           '-BMiB' prints sizes in units of 1,048,576 bytes;\n\
                            see SIZE format below\n\
       --total           produce a grand total\n\
   -h, --human-readable  print sizes in powers of 1024 (e.g., 1023M)\n\
diff --git a/src/du.c b/src/du.c
index 890edb6..215cb21 100644
--- a/src/du.c
+++ b/src/du.c
@@ -299,7 +299,7 @@ Summarize disk usage of each FILE, recursively for directories.\n\
 "), stdout);
       fputs (_("\
   -B, --block-size=SIZE  scale sizes by SIZE before printing them; e.g.,\n\
-                           '-BM' prints sizes in units of 1,048,576 bytes;\n\
+                           '-BMiB' prints sizes in units of 1,048,576 bytes;\n\
                            see SIZE format below\n\
   -b, --bytes           equivalent to '--apparent-size --block-size=1'\n\
   -c, --total           produce a grand total\n\
diff --git a/src/ls.c b/src/ls.c
index 25e10fa..6f5fef7 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -4793,7 +4793,7 @@ Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.\n\
 "), stdout);
       fputs (_("\
       --block-size=SIZE      scale sizes by SIZE before printing them; e.g.,\n\
-                               '--block-size=M' prints sizes in units of\n\
+                               '--block-size=MiB' prints sizes in units of\n\
                                1,048,576 bytes; see SIZE format below\n\
   -B, --ignore-backups       do not list implied entries ending with ~\n\
   -c                         with -lt: sort by, and show, ctime (time of last\n\