Skip to content

Commit 9d02cf9

Browse files
committed
add find_identical_files example program
1 parent 4e89325 commit 9d02cf9

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

examples/find_identical_files.c

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#include "../include/filelist.h"
2+
#include "../include/filelib.h"
3+
#include "../include/logger.h"
4+
#include <string.h>
5+
#include <stdio.h>
6+
7+
static int stringptr_endswithchar(stringptr* s, int ch) {
8+
if(stringptr_getsize(s) == 0) return 0;
9+
return stringptr_get(s)[stringptr_getsize(s)-1] == ch;
10+
}
11+
12+
static int compare_files(stringptr* fn1, stringptr* fn2) {
13+
FILE *f1 = fopen(stringptr_get(fn1), "r");
14+
FILE *f2 = fopen(stringptr_get(fn2), "r");
15+
int ret = 1;
16+
size_t n;
17+
while(1) {
18+
unsigned char buf1[16*1024];
19+
unsigned char buf2[16*1024];
20+
n = fread(buf1, 1, sizeof buf1, f1);
21+
if(n == 0) { ret = 0; break; }
22+
if(n != fread(buf2, 1, sizeof buf2, f2)) break;
23+
if(memcmp(buf1, buf2, n)) break;
24+
}
25+
fclose(f1);
26+
fclose(f2);
27+
return ret;
28+
}
29+
30+
static int mode = 0; /* 0: identical, 1: not identical */
31+
32+
static int process_path(stringptr* dir1, stringptr* dir2) {
33+
filelist fl1, fl2;
34+
int ret;
35+
ret = filelist_search(&fl1, dir1, SPL("*"), FLF_EXCLUDE_PATH|FLF_INCLUDE_HIDDEN);
36+
if(ret) return ret;
37+
ret = filelist_search(&fl2, dir2, SPL("*"), FLF_EXCLUDE_PATH|FLF_INCLUDE_HIDDEN);
38+
if(ret) return ret;
39+
size_t i, j;
40+
for(i=0; i < stringptrlist_getsize(fl1.files); ++i) {
41+
stringptr *f1 = stringptrlist_get(fl1.files, i);
42+
if(!stringptrlist_contains(fl2.files, f1)) continue;
43+
stringptr* full1 = stringptr_concat(dir1, stringptr_endswithchar(dir1, '/') ? SPL("") : SPL("/"), f1, NULL);
44+
stringptr* full2 = stringptr_concat(dir2, stringptr_endswithchar(dir1, '/') ? SPL("") : SPL("/"), f1, NULL);
45+
if(stringptr_endswithchar(f1, '/')) {
46+
ret = process_path(full1, full2);
47+
if(ret) return ret;
48+
goto next;
49+
}
50+
if(getfilesize(stringptr_get(full1)) != getfilesize(stringptr_get(full2)))
51+
if(mode) goto print;
52+
else goto next;
53+
if(compare_files(full1, full2) == mode) {
54+
print:
55+
log_puts(1, full1);
56+
log_putln(1);
57+
}
58+
next:
59+
stringptr_free(full1);
60+
stringptr_free(full2);
61+
}
62+
filelist_free(&fl1);
63+
filelist_free(&fl2);
64+
}
65+
66+
static int usage() {
67+
log_puts(2, SPL(
68+
"usage: PROG MODE DIR1 DIR2\n"
69+
"MODE: i - identical or n - not identical\n"
70+
"finds all (not) identical files in DIR1/2 and its subdirs.\n"
71+
"prints filenames of DIR1 that match MODE.\n"
72+
"files that exist only in DIR1 or DIR2 are excluded.\n"
73+
));
74+
return 1;
75+
}
76+
77+
int main(int argc, char** argv) {
78+
if(argc != 4) return usage();
79+
mode = argv[1][0] == 'i' ? 0 : 1;
80+
SPDECLAREC(dir1, argv[2]);
81+
SPDECLAREC(dir2, argv[3]);
82+
int ret = process_path(dir1, dir2);
83+
return ret;
84+
}

0 commit comments

Comments
 (0)