You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
5.7 KiB
168 lines
5.7 KiB
From e95ec42dc178eff0410880c3dc4c0dac3df442df Mon Sep 17 00:00:00 2001
|
|
From: Adrian Lopez <adrianlopezroche@gmail.com>
|
|
Date: Tue, 23 Aug 2016 18:21:18 -0400
|
|
Subject: [PATCH] Add an option to sort duplicate files by ctime.
|
|
|
|
---
|
|
README | 5 +++--
|
|
fdupes.1 | 2 +-
|
|
fdupes.c | 49 +++++++++++++++++++++++++++++++++++++------------
|
|
3 files changed, 41 insertions(+), 15 deletions(-)
|
|
|
|
diff --git a/README b/README
|
|
index c748d05..c27f043 100644
|
|
--- a/README
|
|
+++ b/README
|
|
@@ -37,8 +37,9 @@ Usage: fdupes [options] DIRECTORY...
|
|
grouping into sets; implies --noprompt
|
|
-p --permissions don't consider files with different owner/group or
|
|
permission bits as duplicates
|
|
- -o --order=BY select sort order for output, linking and deleting; by
|
|
- mtime (BY='time'; default) or filename (BY='name')
|
|
+ -o --order=BY select sort order for output and deleting; by file
|
|
+ modification time (BY='time'; default), status
|
|
+ change time (BY='ctime'), or filename (BY='name')
|
|
-i --reverse reverse order while sorting
|
|
-v --version display fdupes version
|
|
-h --help display this help message
|
|
diff --git a/fdupes.1 b/fdupes.1
|
|
index 5ddad87..969a5d8 100644
|
|
--- a/fdupes.1
|
|
+++ b/fdupes.1
|
|
@@ -72,7 +72,7 @@ don't consider files with different owner/group or permission bits as duplicates
|
|
.TP
|
|
.B -o --order\fR=\fIWORD\fR
|
|
order files according to WORD:
|
|
-time - sort by mtime, name - sort by filename
|
|
+time - sort by modification time, ctime - sort by status change time, name - sort by filename
|
|
.TP
|
|
.B -i --reverse
|
|
reverse order while sorting
|
|
diff --git a/fdupes.c b/fdupes.c
|
|
index ef64c45..7eee165 100644
|
|
--- a/fdupes.c
|
|
+++ b/fdupes.c
|
|
@@ -56,7 +56,8 @@
|
|
#define F_IMMEDIATE 0x8000
|
|
|
|
typedef enum {
|
|
- ORDER_TIME = 0,
|
|
+ ORDER_MTIME = 0,
|
|
+ ORDER_CTIME,
|
|
ORDER_NAME
|
|
} ordertype_t;
|
|
|
|
@@ -64,6 +65,8 @@ char *program_name;
|
|
|
|
unsigned long flags = 0;
|
|
|
|
+ordertype_t ordertype = ORDER_MTIME;
|
|
+
|
|
#define CHUNK_SIZE 8192
|
|
|
|
#define INPUT_SIZE 256
|
|
@@ -97,7 +100,7 @@ typedef struct _file {
|
|
md5_byte_t *crcsignature;
|
|
dev_t device;
|
|
ino_t inode;
|
|
- time_t mtime;
|
|
+ time_t sorttime;
|
|
int hasdupes; /* true only if file is first on duplicate chain */
|
|
struct _file *duplicates;
|
|
struct _file *next;
|
|
@@ -183,6 +186,14 @@ time_t getmtime(char *filename) {
|
|
return s.st_mtime;
|
|
}
|
|
|
|
+time_t getctime(char *filename) {
|
|
+ struct stat s;
|
|
+
|
|
+ if (stat(filename, &s) != 0) return 0;
|
|
+
|
|
+ return s.st_ctime;
|
|
+}
|
|
+
|
|
char **cloneargs(int argc, char **argv)
|
|
{
|
|
int x;
|
|
@@ -435,7 +446,17 @@ void getfilestats(file_t *file)
|
|
file->size = filesize(file->d_name);
|
|
file->inode = getinode(file->d_name);
|
|
file->device = getdevice(file->d_name);
|
|
- file->mtime = getmtime(file->d_name);
|
|
+
|
|
+ switch (ordertype)
|
|
+ {
|
|
+ case ORDER_CTIME:
|
|
+ file->sorttime = getctime(file->d_name);
|
|
+ break;
|
|
+ case ORDER_MTIME:
|
|
+ default:
|
|
+ file->sorttime = getmtime(file->d_name);
|
|
+ break;
|
|
+ }
|
|
}
|
|
|
|
int registerfile(filetree_t **branch, file_t *file)
|
|
@@ -911,11 +932,11 @@ int sort_pairs_by_arrival(file_t *f1, file_t *f2)
|
|
return !ISFLAG(flags, F_REVERSE) ? -1 : 1;
|
|
}
|
|
|
|
-int sort_pairs_by_mtime(file_t *f1, file_t *f2)
|
|
+int sort_pairs_by_time(file_t *f1, file_t *f2)
|
|
{
|
|
- if (f1->mtime < f2->mtime)
|
|
+ if (f1->sorttime < f2->sorttime)
|
|
return !ISFLAG(flags, F_REVERSE) ? -1 : 1;
|
|
- else if (f1->mtime > f2->mtime)
|
|
+ else if (f1->sorttime > f2->sorttime)
|
|
return !ISFLAG(flags, F_REVERSE) ? 1 : -1;
|
|
|
|
return 0;
|
|
@@ -1038,8 +1059,9 @@ void help_text()
|
|
printf(" \tgrouping into sets; implies --noprompt\n");
|
|
printf(" -p --permissions \tdon't consider files with different owner/group or\n");
|
|
printf(" \tpermission bits as duplicates\n");
|
|
- printf(" -o --order=BY \tselect sort order for output, linking and deleting; by\n");
|
|
- printf(" \tmtime (BY='time'; default) or filename (BY='name')\n");
|
|
+ printf(" -o --order=BY \tselect sort order for output and deleting; by file\n");
|
|
+ printf(" \tmodification time (BY='time'; default), status\n");
|
|
+ printf(" \tchange time (BY='ctime'), or filename (BY='name')\n");
|
|
printf(" -i --reverse \treverse order while sorting\n");
|
|
printf(" -v --version \tdisplay fdupes version\n");
|
|
printf(" -h --help \tdisplay this help message\n\n");
|
|
@@ -1061,7 +1083,6 @@ int main(int argc, char **argv) {
|
|
int progress = 0;
|
|
char **oldargv;
|
|
int firstrecurse;
|
|
- ordertype_t ordertype = ORDER_TIME;
|
|
|
|
#ifndef OMIT_GETOPT_LONG
|
|
static struct option long_options[] =
|
|
@@ -1161,7 +1182,9 @@ int main(int argc, char **argv) {
|
|
if (!strcasecmp("name", optarg)) {
|
|
ordertype = ORDER_NAME;
|
|
} else if (!strcasecmp("time", optarg)) {
|
|
- ordertype = ORDER_TIME;
|
|
+ ordertype = ORDER_MTIME;
|
|
+ } else if (!strcasecmp("ctime", optarg)) {
|
|
+ ordertype = ORDER_CTIME;
|
|
} else {
|
|
errormsg("invalid value for --order: '%s'\n", optarg);
|
|
exit(1);
|
|
@@ -1247,10 +1270,12 @@ int main(int argc, char **argv) {
|
|
if (confirmmatch(file1, file2)) {
|
|
if (ISFLAG(flags, F_DELETEFILES) && ISFLAG(flags, F_IMMEDIATE))
|
|
deletesuccessor(match, curfile,
|
|
- (ordertype == ORDER_TIME) ? sort_pairs_by_mtime : sort_pairs_by_filename );
|
|
+ (ordertype == ORDER_MTIME ||
|
|
+ ordertype == ORDER_CTIME) ? sort_pairs_by_time : sort_pairs_by_filename );
|
|
else
|
|
registerpair(match, curfile,
|
|
- (ordertype == ORDER_TIME) ? sort_pairs_by_mtime : sort_pairs_by_filename );
|
|
+ (ordertype == ORDER_MTIME ||
|
|
+ ordertype == ORDER_CTIME) ? sort_pairs_by_time : sort_pairs_by_filename );
|
|
}
|
|
|
|
fclose(file1);
|