Now sort the files by group IDs.
authorFrancois Fleuret <francois@fleuret.org>
Tue, 9 Mar 2010 17:29:04 +0000 (18:29 +0100)
committerFrancois Fleuret <francois@fleuret.org>
Tue, 9 Mar 2010 17:29:04 +0000 (18:29 +0100)
finddup.1
finddup.c

index 2d73865..540b0d4 100644 (file)
--- a/finddup.1
+++ b/finddup.1
@@ -41,7 +41,10 @@ shows the real path of the files
 
 .SH "BUGS"
 
-The display is not sorted by groups.
+None known, probably many. Valgrind does not complain though.
+
+While not a bug per se, the for of the output should definitely be
+improved. Not clear how.
 
 .SH "EXAMPLES"
 .nf
index 5dacc63..983168b 100644 (file)
--- a/finddup.c
+++ b/finddup.c
@@ -105,7 +105,7 @@ struct file_with_size {
   size_t size;
   ino_t inode;
   struct file_with_size *next;
-  int id;
+  int group_id;
 };
 
 void file_list_delete(struct file_with_size *head) {
@@ -224,7 +224,7 @@ struct file_with_size *scan_directory(struct file_with_size *tail,
       tmp->filename = strdup(name);
       tmp->size = sb.st_size;
       tmp->inode = sb.st_ino;
-      tmp->id = -1;
+      tmp->group_id = -1;
       tail = tmp;
     }
   }
@@ -233,21 +233,82 @@ struct file_with_size *scan_directory(struct file_with_size *tail,
 }
 
 void print_file(struct file_with_size *node) {
+  char tmp[PATH_MAX];
   if(show_realpaths) {
     if(show_groups) {
-      printf("%d %s\n", node->id, realpath(node->filename, 0));
+      realpath(node->filename, tmp);
+      printf("%d %s\n", node->group_id, tmp);
     } else {
-      printf("%s\n", realpath(node->filename, 0));
+      realpath(node->filename, tmp);
+      printf("%s\n", tmp);
     }
   } else {
     if(show_groups) {
-      printf("%d %s\n", node->id, node->filename);
+      printf("%d %s\n", node->group_id, node->filename);
     } else {
       printf("%s\n", node->filename);
     }
   }
 }
 
+int compare_nodes(const void *x1, const void *x2) {
+  const struct file_with_size **f1, **f2;
+
+  f1 = (const struct file_with_size **) x1;
+  f2 = (const struct file_with_size **) x2;
+
+  if((*f1)->group_id < (*f2)->group_id) {
+    return -1;
+  } else if((*f1)->group_id > (*f2)->group_id) {
+    return 1;
+  } else {
+    return 0;
+  }
+}
+
+
+void print_result(struct file_with_size *list1, struct file_with_size *list2) {
+  struct file_with_size *node1, *node2;
+  struct file_with_size **nodes;
+  int nb, n;
+
+  nb = 0;
+  for(node1 = list1; node1; node1 = node1->next) {
+    if(node1->group_id >= 0) { nb++; }
+  }
+
+  if(show_hits) {
+    for(node2 = list2; node2; node2 = node2->next) {
+      if(node2->group_id >= 0) { nb++; }
+    }
+  }
+
+  nodes = safe_malloc(nb * sizeof(struct file_with_size *));
+
+  n = 0;
+  for(node1 = list1; node1; node1 = node1->next) {
+    if(node1->group_id >= 0) {
+      nodes[n++] = node1;
+    }
+  }
+
+  if(show_hits) {
+    for(node2 = list2; node2; node2 = node2->next) {
+      if(node2->group_id >= 0) {
+        nodes[n++] = node2;
+      }
+    }
+  }
+
+  qsort(nodes, nb, sizeof(struct file_with_size *), compare_nodes);
+
+  for(n = 0; n < nb; n++) {
+    print_file(nodes[n]);
+  }
+
+  free(nodes);
+}
+
 void start(const char *dirname1, const char *dirname2) {
   struct file_with_size *list1, *list2;
   struct file_with_size *node1, *node2;
@@ -339,26 +400,24 @@ void start(const char *dirname1, const char *dirname2) {
 
       for(node2 = list2; node2; node2 = node2->next) {
         if(node1->inode != node2->inode && same_files(node1, node2)) {
-          if(node1->id < 0) {
-            if(node2->id >= 0) {
-              node1->id = node2->id;
+          if(node1->group_id < 0) {
+            if(node2->group_id >= 0) {
+              node1->group_id = node2->group_id;
             } else {
-              node1->id = k;
+              node1->group_id = k;
               k++;
             }
-            print_file(node1);
           }
-          if(node2->id < 0) {
-            node2->id = node1->id;
-            if(show_hits) {
-              print_file(node2);
-            }
+          if(node2->group_id < 0) {
+            node2->group_id = node1->group_id;
           }
         }
       }
     }
   }
 
+  print_result(list1, list2);
+
   file_list_delete(list1);
   if(!same_dir) {
     file_list_delete(list2);