Now able to list files existing in DIR1 which do not in DIR2.
authorFrancois Fleuret <francois@fleuret.org>
Sun, 7 Mar 2010 22:25:32 +0000 (23:25 +0100)
committerFrancois Fleuret <francois@fleuret.org>
Sun, 7 Mar 2010 22:25:32 +0000 (23:25 +0100)
Makefile
finddup.1
finddup.c

index 235ac49..d02a4d9 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -26,7 +26,7 @@ MAN_PATH = /usr/share/man/man1
 
 LDFLAGS=
 
 
 LDFLAGS=
 
-REVISION_NUMBER=\"$(shell cat REVISION_NUMBER)\"
+UNAME=\"$(shell uname -srmn)\"
 
 ifeq ($(DEBUG),yes)
   OPTIMIZE_FLAG = -ggdb3 -DDEBUG -fno-omit-frame-pointer
 
 ifeq ($(DEBUG),yes)
   OPTIMIZE_FLAG = -ggdb3 -DDEBUG -fno-omit-frame-pointer
@@ -34,7 +34,7 @@ else
   OPTIMIZE_FLAG = -O2
 endif
 
   OPTIMIZE_FLAG = -O2
 endif
 
-CFLAGS = -Wall -ansi -pedantic -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DREVISION_NUMBER=$(REVISION_NUMBER) $(OPTIMIZE_FLAG)
+CFLAGS = -Wall -ansi -pedantic -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DUNAME="$(UNAME)" $(OPTIMIZE_FLAG)
 
 all: finddup
 
 
 all: finddup
 
index 36ae5a3..989cff9 100644 (file)
--- a/finddup.1
+++ b/finddup.1
@@ -10,7 +10,7 @@ finddup \- Find files common to several directories or not
 
 .SH "SYNOPSIS"
 
 
 .SH "SYNOPSIS"
 
-\fBfinddup\fP [OPTION]... [FILE]...
+\fBfinddup\fP [OPTION]... DIR1 [[^]DIR2]
 
 .SH "DESCRIPTION"
 
 
 .SH "DESCRIPTION"
 
@@ -18,6 +18,12 @@ finddup \- Find files common to several directories or not
 common to two directories or files existing in one directories and not
 in another one.
 
 common to two directories or files existing in one directories and not
 in another one.
 
+With a single directory argument, prints the duplicate files found in
+it. With two directories, prints the files common to both.
+
+If the second directory name starts with a ^, prints the files
+existing in DIR1 which do not exist in DIR2.
+
 .SH "OPTIONS"
 .TP
 \fB-h\fR
 .SH "OPTIONS"
 .TP
 \fB-h\fR
@@ -28,7 +34,8 @@ shows the real path of the files
 
 .SH "BUGS"
 
 
 .SH "BUGS"
 
-None known, probably many though.
+Every pair of different files with same content are listed, which
+results in K^2 printed lines when K files are similar.
 
 .SH "AUTHOR"
 
 
 .SH "AUTHOR"
 
index 09c50d1..39a3df6 100644 (file)
--- a/finddup.c
+++ b/finddup.c
@@ -46,19 +46,11 @@ typedef int64_t size_sum_t;
 int ignore_dotfiles = 0; /* 1 means ignore files and directories
                             starting with a dot */
 
 int ignore_dotfiles = 0; /* 1 means ignore files and directories
                             starting with a dot */
 
-int forced_width = 0; /* -1 means no width limit, strictly positive
-                         means limit, 0 means not active */
-
-int forced_height = 0; /* -1 means no height limit, strictly positive
-                           means limit, 0 means not active */
-
-int fancy_size_display = 0; /* 1 means to use floating values with K, M and G
-                               as units */
-
-int reverse_sorting = 0; /* 1 means to show the large ones first */
+int show_realpaths = 0; /* 1 means ignore files and directories
+                            starting with a dot */
 
 
-int show_top = 0; /* 1 means to show the top of the sorted list
-                     instead of the bottom */
+int show_progress = 1; /* 1 means show a progress bar when we are in a
+                          tty */
 
 /********************************************************************/
 
 
 /********************************************************************/
 
@@ -152,6 +144,8 @@ int same_content(struct file_with_size *f1, struct file_with_size *f2) {
 
       if(s1 == s2) {
         if(s1 == 0) {
 
       if(s1 == s2) {
         if(s1 == 0) {
+          close(fd1);
+          close(fd2);
           return 1;
         } else {
           if(strncmp(buffer1, buffer2, s1)) {
           return 1;
         } else {
           if(strncmp(buffer1, buffer2, s1)) {
@@ -167,6 +161,8 @@ int same_content(struct file_with_size *f1, struct file_with_size *f2) {
       }
     }
   } else {
       }
     }
   } else {
+    if(fd1 >= 0) { close(fd1); }
+    if(fd2 >= 0) { close(fd2); }
     return 0;
   }
 }
     return 0;
   }
 }
@@ -183,10 +179,10 @@ struct file_with_size *scan_directory(struct file_with_size *tail,
   struct dirent *dir_e;
   struct stat dummy;
   struct file_with_size *tmp;
   struct dirent *dir_e;
   struct stat dummy;
   struct file_with_size *tmp;
-  char subname[BUFFER_SIZE];
+  char subname[PATH_MAX];
 
   if(lstat(name, &dummy) != 0) {
 
   if(lstat(name, &dummy) != 0) {
-    fprintf(stderr, "Can not stat %s: %s\n", name, strerror(errno));
+    fprintf(stderr, "Can not stat \"%s\": %s\n", name, strerror(errno));
     exit(EXIT_FAILURE);
   }
 
     exit(EXIT_FAILURE);
   }
 
@@ -199,7 +195,7 @@ struct file_with_size *scan_directory(struct file_with_size *tail,
   if(dir) {
     while((dir_e = readdir(dir))) {
       if(!ignore_entry(dir_e->d_name)) {
   if(dir) {
     while((dir_e = readdir(dir))) {
       if(!ignore_entry(dir_e->d_name)) {
-        snprintf(subname, BUFFER_SIZE, "%s/%s", name, dir_e->d_name);
+        snprintf(subname, PATH_MAX, "%s/%s", name, dir_e->d_name);
         tail = scan_directory(tail, subname);
       }
     }
         tail = scan_directory(tail, subname);
       }
     }
@@ -221,13 +217,50 @@ struct file_with_size *scan_directory(struct file_with_size *tail,
 void start(const char *dirname1, const char *dirname2) {
   struct file_with_size *list1, *list2;
   struct file_with_size *node1, *node2;
 void start(const char *dirname1, const char *dirname2) {
   struct file_with_size *list1, *list2;
   struct file_with_size *node1, *node2;
+  int not_in, found;
+
+  if(dirname2[0] == '^') {
+    not_in = 1;
+    dirname2++;
+  } else {
+    not_in = 0;
+  }
+
   list1 = scan_directory(0, dirname1);
   list2 = scan_directory(0, dirname2);
 
   list1 = scan_directory(0, dirname1);
   list2 = scan_directory(0, dirname2);
 
-  for(node1 = list1; node1; node1 = node1->next) {
-    for(node2 = list2; node2; node2 = node2->next) {
-      if(node1->inode != node2->inode && same_files(node1, node2)) {
-        printf("%s %s \n", node1->filename, node2->filename);
+  if(not_in) {
+    for(node1 = list1; node1; node1 = node1->next) {
+      found = 0;
+
+      for(node2 = list2; !found && node2; node2 = node2->next) {
+        if(node1->inode != node2->inode && same_files(node1, node2)) {
+          found = 1;
+        }
+      }
+
+      if(!found) {
+        if(show_realpaths) {
+          printf("%s\n", realpath(node1->filename, 0));
+        } else {
+          printf("%s\n", node1->filename);
+        }
+      }
+    }
+
+  } else {
+
+    for(node1 = list1; node1; node1 = node1->next) {
+      for(node2 = list2; node2; node2 = node2->next) {
+        if(node1->inode != node2->inode && same_files(node1, node2)) {
+          if(show_realpaths) {
+            printf("%s %s\n",
+                   realpath(node1->filename, 0),
+                   realpath(node2->filename, 0));
+          } else {
+            printf("%s %s\n", node1->filename, node2->filename);
+          }
+        }
       }
     }
   }
       }
     }
   }
@@ -247,7 +280,7 @@ int main(int argc, char **argv) {
   setlocale (LC_ALL, "");
 
   while (1) {
   setlocale (LC_ALL, "");
 
   while (1) {
-    c = getopt(argc, argv, "h");
+    c = getopt(argc, argv, "hr");
     if (c == -1)
       break;
 
     if (c == -1)
       break;
 
@@ -260,6 +293,10 @@ int main(int argc, char **argv) {
 
       break;
 
 
       break;
 
+    case 'r':
+      show_realpaths = 1;
+      break;
+
     default:
       exit(EXIT_FAILURE);
     }
     default:
       exit(EXIT_FAILURE);
     }
@@ -267,8 +304,10 @@ int main(int argc, char **argv) {
 
   if(optind + 1 < argc) {
     start(argv[optind], argv[optind + 1]);
 
   if(optind + 1 < argc) {
     start(argv[optind], argv[optind + 1]);
+  } else if(optind < argc) {
+    start(argv[optind], argv[optind]);
   } else {
   } else {
-    fprintf(stderr, "%s [OPTIONS] <dir1> <dir2>\n", argv[0]);
+    fprintf(stderr, "%s [OPTIONS] <dir1> [[^]<dir2>]\n", argv[0]);
     exit(EXIT_FAILURE);
   }
 
     exit(EXIT_FAILURE);
   }