Subject: bin/14687: Addition of -h to du(1)
To: None <gnats-bugs@gnats.netbsd.org>
From: None <tsn@gbdev.net>
List: netbsd-bugs
Date: 11/23/2001 01:28:18
>Number:         14687
>Category:       bin
>Synopsis:       Addition of -h to du(1)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Thu Nov 22 17:29:00 PST 2001
>Closed-Date:
>Last-Modified:
>Originator:     Tomas Svensson
>Release:        NetBSD 1.5Y
>Organization:
	
>Environment:
		NetBSD 1.5Y from 20th Nov

>Description:
		I've added -h to du(1) to display sizes in a more "human-
		readable" and compact form. Exists in FreeBSD and GNU but
		my implementation is more correct and shares no code with
		theirs.

		Example output from df -h (a lot of lines cut)


		 282K	./yacc
		 4.0K	./yes/CVS
		  12K	./yes
		 4.0K	./ypcat/CVS
		  14K	./ypcat
		 4.0K	./ypmatch/CVS
		  14K	./ypmatch
		 4.0K	./ypwhich/CVS
		  21K	./ypwhich
		  14M	.

		most replies on tech-userlevel were positive to adding
		this flag.
>How-To-Repeat:
	
>Fix:

Index: du.1
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/du/du.1,v
retrieving revision 1.10
diff -u -r1.10 du.1
--- du.1	2001/07/08 15:34:14	1.10
+++ du.1	2001/11/22 12:08:59
@@ -43,7 +43,7 @@
 .Nm
 .Op Fl H | Fl L | Fl P
 .Op Fl a | Fl s
-.Op Fl ckmrx
+.Op Fl chkmrx
 .Op Ar file ...
 .Sh DESCRIPTION
 The
@@ -65,6 +65,12 @@
 No symbolic links are followed.
 .It Fl a
 Display an entry for each file in the file hierarchy.
+.It Fl c
+Display the grand total after all the arguments have been processed.
+.It Fl h
+Display sizes in a more "human-readable" and compact form. Use unit suffixes: 
+Byte, Kilobyte, Megabyte, Gigabyte, Terabyte, Petabyte and Exabyte in order to
+reduce the number of digits to four or fewer using base 2 for sizes.
 .It Fl k
 By default,
 .Nm
@@ -80,8 +86,6 @@
 .Fl m
 flag is specified, the number displayed is the number of megabyte 
 (1024*1024 bytes) blocks.
-.It Fl c
-Display the grand total after all the arguments have been processed.
 .It Fl r
 Generate warning messages about directories that cannot be read.
 This is the default behaviour.
@@ -122,6 +126,7 @@
 If the environment variable
 .Ev BLOCKSIZE
 is set, and the 
+.Fl h
 .Fl k 
 and
 .Fl m
Index: du.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/du/du.c,v
retrieving revision 1.17
diff -u -r1.17 du.c
--- du.c	2001/01/04 23:05:54	1.17
+++ du.c	2001/11/22 12:09:00
@@ -64,6 +64,7 @@
 
 int	linkchk __P((FTSENT *));
 int	main __P((int, char **));
+void	prthuman(int64_t);
 void	usage __P((void));
 
 int
@@ -75,14 +76,15 @@
 	FTSENT *p;
 	long blocksize, totalblocks;
 	int ftsoptions, listdirs, listfiles;
-	int Hflag, Lflag, Pflag, aflag, ch, cflag, kmflag, notused, rval, sflag;
+	int Hflag, Lflag, Pflag, aflag, ch, cflag, hflag, kmflag, notused,
+	    rval, sflag;
 	char **save;
 
 	save = argv;
-	Hflag = Lflag = Pflag = aflag = cflag = kmflag = sflag = 0;
+	Hflag = Lflag = Pflag = aflag = cflag = hflag = kmflag = sflag = 0;
 	totalblocks = 0;
 	ftsoptions = FTS_PHYSICAL;
-	while ((ch = getopt(argc, argv, "HLPackmrsx")) != -1)
+	while ((ch = getopt(argc, argv, "HLPachkmrsx")) != -1)
 		switch (ch) {
 		case 'H':
 			Hflag = 1;
@@ -102,6 +104,9 @@
 		case 'c':
 			cflag = 1;
 			break;
+		case 'h':
+			hflag = 1;
+			break;
 		case 'k':
 			blocksize = 1024;
 			kmflag = 1;
@@ -182,10 +187,16 @@
 			 * or directories and this is post-order of the
 			 * root of a traversal, display the total.
 			 */
-			if (listdirs || (!listfiles && !p->fts_level))
-				(void)printf("%ld\t%s\n",
-				    howmany(p->fts_number, blocksize),
-				    p->fts_path);
+			if (listdirs || (!listfiles && !p->fts_level)) {
+				if (hflag) {  
+					prthuman(howmany(p->fts_number, 
+					    blocksize) * blocksize * 512);
+					(void)printf("\t%s\n",p->fts_path);
+				} else
+					(void)printf("%ld\t%s\n",
+				    	    howmany(p->fts_number, blocksize),
+				    	    p->fts_path);
+			}
 			break;
 		case FTS_DC:			/* Ignore. */
 			break;
@@ -202,19 +213,32 @@
 			 * If listing each file, or a non-directory file was
 			 * the root of a traversal, display the total.
 			 */
-			if (listfiles || !p->fts_level)
-				(void)printf("%lld\t%s\n", (long long)
-				    howmany(p->fts_statp->st_blocks, blocksize),
-				    p->fts_path);
+			if (listfiles || !p->fts_level) {
+				if (hflag) {
+					prthuman(howmany(p->fts_statp->\
+					    st_blocks, blocksize) * blocksize
+					    * 512);
+					(void)printf("\t%s\n",p->fts_path);
+				} else
+					(void)printf("%lld\t%s\n", (long long)
+				    	    howmany(p->fts_statp->st_blocks,
+					    blocksize), p->fts_path);
+			}
 			p->fts_parent->fts_number += p->fts_statp->st_blocks;
 			if (cflag)
 				totalblocks += p->fts_statp->st_blocks;
 		}
 	if (errno)
 		err(1, "fts_read");
-	if (cflag)
-		(void)printf("%ld\ttotal\n",
-		    howmany(totalblocks, blocksize));
+	if (cflag) {
+		if (hflag) {
+			prthuman(howmany(totalblocks, blocksize) * blocksize
+			* 512);
+			(void)printf("\ttotal\n");
+		} else
+			(void)printf("%ld\ttotal\n",
+		    	    howmany(totalblocks, blocksize));
+	}
 	exit(0);
 }
 
@@ -249,11 +273,45 @@
 	return (0);
 }
 
+/*
+ * Print size in a more "human-readable" and compact form.
+ */
+void
+prthuman(int64_t bytes)
+{
+        int i, size1, size2, unit;
+                 
+        if (bytes == 0)
+                (void)printf("   0B");
+        else {
+                i = 0;
+		bytes *= 100;
+                for(unit = -1; unit == -1; i++)
+                        if (bytes < 102400 || i == 6)
+                                unit = i;
+                        else
+                                bytes /= 1024;
+                if (bytes >= 1000)
+                        (void)printf("%4lli%c",((bytes + 50) / 100),
+                            "BKMGTPE"[unit]);
+                else {
+                        size1 = bytes / 100;
+                        if ((size2 = (((bytes % 100) + 5) / 10)) == 10) {
+                                size1++;
+                                size2 = 0;
+                        }
+                        (void)printf(" %1i.%1i%c", size1, size2,
+			    "BKMGTPE"[unit]);
+                }
+        }
+}
+
+
 void
 usage()
 {
 
 	(void)fprintf(stderr,
-		"usage: du [-H | -L | -P] [-a | -s] [-ckmrx] [file ...]\n");
+		"usage: du [-H | -L | -P] [-a | -s] [-chkmrx] [file ...]\n");
 	exit(1);
 }
>Release-Note:
>Audit-Trail:
>Unformatted: