Additions to du

Kim Ahlström <[email protected]>
Newsgroups gmane.comp.gnu.fileutils.bugs
Message-ID <[email protected]>
Hi!

I have have made two additions to the du utility that I thought you 
might want to take a look at.

First. The addition of a -p flag. When this is used the file's size in 
percent relative to the total number of shown files will be printed. A 
downside to this is that du has to go through all files first before it 
can start producing output, thus making it silent for a moment.

Example:
% src/du  -p /Users/kim/temp/fileutils-4.1.11/tests/
3.94%   /Users/kim/temp/fileutils-4.1.11/tests/chgrp
4.33%   /Users/kim/temp/fileutils-4.1.11/tests/chmod
3.15%   /Users/kim/temp/fileutils-4.1.11/tests/chown
11.81%  /Users/kim/temp/fileutils-4.1.11/tests/cp
...

Second. The three kinds of output flags -kmbB, -hH and -p can now be 
given simultaneously and will all output their respective data followed 
by a tab. -kmb will print first, then -hH and last -p.

Like this:
% src/du  -p /Users/kim/temp/fileutils-4.1.11/tests/
40      40K     3.94%   /Users/kim/temp/fileutils-4.1.11/tests/chgrp
44      44K     4.33%   /Users/kim/temp/fileutils-4.1.11/tests/chmod
32      32K     3.15%   /Users/kim/temp/fileutils-4.1.11/tests/chown
120     120K    11.81%  /Users/kim/temp/fileutils-4.1.11/tests/cp
...

or:
% src/du  -bh /Users/kim/temp/fileutils-4.1.11/tests/
40960   40K     /Users/kim/temp/fileutils-4.1.11/tests/chgrp
45056   44K     /Users/kim/temp/fileutils-4.1.11/tests/chmod
32768   32K     /Users/kim/temp/fileutils-4.1.11/tests/chown
122880  120K    /Users/kim/temp/fileutils-4.1.11/tests/cp
...

or:
% src/du -p -B 5K /Users/kim/temp/fileutils-4.1.11/tests/
8       3.94%   /Users/kim/temp/fileutils-4.1.11/tests/chgrp
9       4.33%   /Users/kim/temp/fileutils-4.1.11/tests/chmod
7       3.15%   /Users/kim/temp/fileutils-4.1.11/tests/chown
24      11.81%  /Users/kim/temp/fileutils-4.1.11/tests/cp
...

Included is a diff file that was made with du.c of version 4.1.11 of the 
GNU Fileutils. If you want one that was made with the latest stable 
(4.1) instead I will more than gladly send one over.

I have tried to adhere to the GNU coding standards as thoroughly as 
possible and commented the code where I thought needed. I also wrote a 
ChangeLog entry to clarify code changes.

ChangeLog:
2002-09-18  Kim Ahlstrom  <[email protected]>

	Added -p flag that prints percentage of file's size relative to all 
printed
	files' size. New output handling.

	* src/du.c: Added global variables to handle the new -p flag and 
output options.
	(print_size): Rewrite to allow output from both the -kmb flags,
	the -hH flags and the new -p flag at the same time. Added code to 
accumulate
	data for percentage calculation (-p flag).
	(du_files): Print files and data accumulated by percentage 
calculation (-p flag).
	(main): Added -p flag switch-case. Modified h,H,k,m,b,B 
switch-cases to allow
	the -h and -H flags being active while either -kmbB flags are active.
	(usage): Explain -p flag.


If you have any questions I will be more than happy to answer!

Best Regards

Kim Ahlstrom
[email protected]
http://kim.animanga.nu/ (Swedish only)
du.c.diff (application/octet-stream, 6.5 KB)
--- ../../du.4111.orig.c	Wed Jul 10 10:09:05 2002
+++ du.c	Thu Sep 19 22:21:36 2002
@@ -99,6 +99,31 @@
 int stat ();
 int lstat ();
 
+/* Linked list structure to hold filepaths and n_blocks,
+   to be used with the -p flag for percentage.  */
+
+struct list_def
+{
+  char * path;				/* Filepath (dynamically allocated) */
+  uintmax_t size;			/* Number of n_blocks ( print_size()'s first argument ) */
+  struct list_def *next;	/* Next node */
+};
+
+/* Nodes in the linked list of filepaths and n_blocks.  */
+struct list_def *first_node, *last_node, *now_node = NULL;
+
+/* If nonzero, suppress printing.  */
+static int suppress = 0;
+
+/* If nonzero, calculate percentages (-p).  */
+static int display_percentage = 0;
+
+/* If nonzero, one of the -kmbB flags has been provided.  */
+static int display_byte_kilo_mega = 0;
+
+/* Holds the output_block_size for human numbers (-h or -H).  */
+static int h_block_size = 0;
+
 /* Name under which this program was invoked.  */
 char *program_name;
 
@@ -168,6 +193,7 @@
   {"kilobytes", no_argument, NULL, 'k'}, /* long form is obsolescent */
   {"max-depth", required_argument, NULL, MAX_DEPTH_OPTION},
   {"megabytes", no_argument, NULL, 'm'}, /* obsolescent */
+  {"percent", no_argument, NULL, "p"},
   {"one-file-system", no_argument, NULL, 'x'},
   {"separate-dirs", no_argument, NULL, 'S'},
   {"summarize", no_argument, NULL, 's'},
@@ -208,6 +234,7 @@
 "), stdout);
       fputs (_("\
   -L, --dereference     dereference all symbolic links\n\
+  -p, --percent         print sizes in percent relative to all files' total size\n\
   -S, --separate-dirs   do not include size of subdirectories\n\
   -s, --summarize       display only a total for each argument\n\
 "), stdout);
@@ -353,20 +380,94 @@
     }
 }
 
-/* Print N_BLOCKS followed by STRING on a line.  NBLOCKS is the number of
-   ST_NBLOCKSIZE-byte blocks; convert it to OUTPUT_BLOCK_SIZE units before
-   printing.  If OUTPUT_BLOCK_SIZE is negative, use a human readable
-   notation instead.  */
+/* If -p flag was provided we start by accumulating file data and not printing.
+   Printing will be requested by the du_files function after accumulation.
+   Print N_BLOCKS[\thuman_readable\tpercentage]\tSTRING on a line.
+   N_BLOCKS is the number of ST_NBLOCKSIZE-byte blocks; convert it to
+   OUTPUT_BLOCK_SIZE units before printing.  If OUTPUT_BLOCK_SIZE is negative,
+   use a human readable notation instead.  */
 
 static void
 print_size (uintmax_t n_blocks, const char *string)
 {
   char buf[LONGEST_HUMAN_READABLE + 1];
-  printf ("%s\t%s\n",
-	  human_readable_inexact (n_blocks, buf, ST_NBLOCKSIZE,
-				  output_block_size, human_ceiling),
-	  string);
-  fflush (stdout);
+  double prcnt; /* Temporary variable to hold the percent.  */
+  
+  if (suppress != 0)
+    {
+      /* The p flag is on and we are accumulating file data.
+         Thus we don't want to print.  */
+      
+      now_node = malloc (sizeof (struct list_def));
+      if (now_node == NULL)
+        {
+          fprintf (stderr, "%s: %s", program_name, strerror (errno));
+          exit (1);
+        }
+    
+      if (first_node == NULL)
+        {
+          first_node = now_node;
+          now_node->next = NULL;
+        }
+      else
+        {
+          last_node->next = now_node;
+          now_node->next = NULL;
+        }
+    
+      last_node = now_node;
+    
+      now_node->path = malloc (strlen (string));
+      if (now_node->path == NULL)
+        {
+          fprintf (stderr, "%s: %s", program_name, strerror (errno));
+          exit (1);
+        }
+      
+      strncpy (now_node->path, string, strlen (string) + 1);
+      now_node->size = n_blocks;
+    }
+  else
+    {
+      /* Print.  */
+      if (display_byte_kilo_mega != 0)
+        {
+          /* Bytes, Kilobytes, Megabytes (-kmbB).  */
+          printf ("%s\t",
+            human_readable_inexact (n_blocks, buf, ST_NBLOCKSIZE,
+	  				output_block_size, human_ceiling));
+	    }
+	  if (h_block_size != 0)
+	    {
+	      /* Human form (-hH).  */
+          printf ("%s\t",
+	        human_readable_inexact (n_blocks, buf, ST_NBLOCKSIZE,
+	    			h_block_size, human_ceiling));
+        }
+      if (display_percentage != 0)
+        {
+          /* Percentage (-p).  */
+          prcnt = ( (double)n_blocks / (double)tot_size) * 100;
+          printf ("%.2f%%\t", prcnt);
+        }
+        
+      if (display_byte_kilo_mega == 0 && h_block_size == 0 && display_percentage == 0)
+        {
+          /* No output flags were provided.  */
+          printf ("%s\t%s\n",
+	        human_readable_inexact (n_blocks, buf, ST_NBLOCKSIZE,
+	      			output_block_size, human_ceiling),
+	        string);
+        }
+      else
+        {
+          /* Filepath.  */
+          printf ("%s\n", string);
+        }
+      
+      fflush (stdout);
+    }
 }
 
 /* Restore the previous working directory or exit.
@@ -553,6 +654,17 @@
       count_entry (arg, 1, 0, 0);
     }
 
+  /* If the -p flag was provided,
+     stop suppressing printing and print the accumulated data.  */
+  if (display_percentage != 0)
+    {
+      suppress = 0;
+      for (now_node = first_node; now_node != NULL; now_node = now_node->next)
+        {
+          print_size (now_node->size, now_node->path);
+        }
+    }
+
   if (print_totals)
     print_size (tot_size, _("total"));
 }
@@ -582,7 +694,7 @@
 
   human_block_size (getenv ("DU_BLOCK_SIZE"), 0, &output_block_size);
 
-  while ((c = getopt_long (argc, argv, "abchHklmsxB:DLSX:", long_options, NULL))
+  while ((c = getopt_long (argc, argv, "abchHklmpsxB:DLSX:", long_options, NULL))
 	 != -1)
     {
       long int tmp_long;
@@ -597,22 +709,33 @@
 
 	case 'b':
 	  output_block_size = 1;
+	  display_byte_kilo_mega = 1;
 	  break;
 
 	case 'c':
 	  print_totals = 1;
 	  break;
 
+	case 'p':
+	  suppress = 1;
+	  display_percentage = 1;
+	  break;
+
 	case 'h':
-	  output_block_size = -1024;
+	  h_block_size = -1024;
+	  if(!display_byte_kilo_mega)
+	    output_block_size = -1024;
 	  break;
 
 	case 'H':
-	  output_block_size = -1000;
+	  h_block_size = -1000;
+	  if(!display_byte_kilo_mega)
+	    output_block_size = -1000;
 	  break;
 
 	case 'k':
 	  output_block_size = 1024;
+	  display_byte_kilo_mega = 1;
 	  break;
 
 	case MAX_DEPTH_OPTION:		/* --max-depth=N */
@@ -626,6 +749,7 @@
 
 	case 'm': /* obsolescent */
 	  output_block_size = 1024 * 1024;
+	  display_byte_kilo_mega = 1;
 	  break;
 
 	case 'l':
@@ -642,6 +766,7 @@
 
 	case 'B':
 	  human_block_size (optarg, 1, &output_block_size);
+	  display_byte_kilo_mega = 1;
 	  break;
 
 	case 'D':
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.