From a630a4504f106bb2de1aadc69ce0a162418bc632 Mon Sep 17 00:00:00 2001 From: Thomas <71355143+thomas694@users.noreply.github.com> Date: Wed, 6 Sep 2023 22:20:44 +0200 Subject: [PATCH] Add option to skip linked duplicates and show only unlinked ones --- README.md | 2 ++ finddupe.c | 26 ++++++++++++++++++-------- version.h | 4 ++-- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 713c4b8..28dc4dd 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ I added the following features to finddupe: - support for ignoring files by patterns (v1.26) - checking for NTFS file system in batch and hardlink mode (v1.27) - performance optimizations (especially for very large amounts of files) (v1.28) +- new option to skip linked duplicates in output list (v1.30) It works for me, but some more testing is desirable. @@ -45,6 +46,7 @@ Options: -z Do not skip zero length files (zero length files are ignored by default) -u Do not print a warning for files that cannot be read + -sl Skip linked duplicates and show only unlinked ones -p Hide progress indicator (useful when redirecting to a file) -j Follow NTFS junctions and reparse points (off by default) -listlink hardlink list mode. Not valid with -del, -bat, -hardlink, diff --git a/finddupe.c b/finddupe.c index fc07f2e..ed295c4 100644 --- a/finddupe.c +++ b/finddupe.c @@ -24,6 +24,8 @@ // performance optimizations (especially for very large amounts of files) // Version 1.29 (c) Aug 2023 thomas694 // fixed a problem with large files +// Version 1.30 (c) Sep 2023 thomas694 +// added option to skip linked duplicates in output list // // finddupe is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -39,7 +41,7 @@ // along with this program. If not, see . //-------------------------------------------------------------------------- -#define VERSION "1.29" +#define VERSION "1.30" #define REF_CODE @@ -147,6 +149,7 @@ int SkipZeroLength = 1; // Ignore zero length files. int ProgressIndicatorVisible = 0; // Weither a progress indicator needs to be overwritten. int FollowReparse = 0; // Whether to follow reparse points (like unix softlinks for NTFS) int MeasureDurations = 0; // Measure how many ticks the different tasks take +int SkipLinkedDuplicates = 0; // Skip linked duplicates and show only unlinked ones TCHAR* * IgnorePatterns; // Patterns of filename to ignore (can be repeated, eg. .bak, .tmp) int IgnorePatternsAlloc; // Number of allocated ignore patterns @@ -342,9 +345,11 @@ static int EliminateDuplicate(FileData_t ThisFile, FileData_t DupeOf) if (PrintDuplicates){ if (!HardlinkSearchMode){ ClearProgressInd(); - _tprintf(TEXT("Duplicate: '%s'\n"), DupeOf.FileName); - _tprintf(TEXT("With: '%s'\n"), ThisFile.FileName); - if (Hardlinked){ + if (!(Hardlinked && SkipLinkedDuplicates)) { + _tprintf(TEXT("Duplicate: '%s'\n"), DupeOf.FileName); + _tprintf(TEXT("With: '%s'\n"), ThisFile.FileName); + } + if (Hardlinked && !SkipLinkedDuplicates) { // If the files happen to be hardlinked, show that. _tprintf(TEXT(" (hardlinked instances of same file)\n")); } @@ -887,6 +892,7 @@ static void Usage (void) TEXT(" -z Do not skip zero length files (zero length files are ignored\n") TEXT(" by default)\n") TEXT(" -u Do not print a warning for files that cannot be read\n") + TEXT(" -sl Skip linked duplicates and show only unlinked ones\n") TEXT(" -p Hide progress indicator (useful when redirecting to a file)\n") TEXT(" -j Follow NTFS junctions and reparse points (off by default)\n") TEXT(" -listlink hardlink list mode. Not valid with -del, -bat, -hardlink,\n") @@ -947,8 +953,8 @@ int _tmain (int argc, TCHAR **argv) arg = argv[argn]; if (indexFirstRef == 0 && !_tcscmp(arg, TEXT("-ref"))) indexFirstRef = argn; if (indexFirstRef > 0 && (!_tcscmp(arg, TEXT("-bat")) || !_tcscmp(arg, TEXT("-v")) || !_tcscmp(arg, TEXT("-sigs")) || !_tcscmp(arg, TEXT("-hardlink")) || - !_tcscmp(arg, TEXT("-del")) || !_tcscmp(arg, TEXT("-rdonly")) || !_tcscmp(arg, TEXT("-listlink")) || !_tcscmp(arg, TEXT("-z")) || - !_tcscmp(arg, TEXT("-u")) || !_tcscmp(arg, TEXT("-p")) || !_tcscmp(arg, TEXT("-j")) || !_tcscmp(arg, TEXT("-ign"))) && argn > indexFirstRef) { + !_tcscmp(arg, TEXT("-del")) || !_tcscmp(arg, TEXT("-rdonly")) || !_tcscmp(arg, TEXT("-listlink")) || !_tcscmp(arg, TEXT("-z")) || !_tcscmp(arg, TEXT("-u")) || + !_tcscmp(arg, TEXT("-sl")) || !_tcscmp(arg, TEXT("-p")) || !_tcscmp(arg, TEXT("-j")) || !_tcscmp(arg, TEXT("-ign"))) && argn > indexFirstRef) { _ftprintf(stderr, TEXT("Wrong order of options! Use -h for help\n")); exit(EXIT_FAILURE); } @@ -985,6 +991,8 @@ int _tmain (int argc, TCHAR **argv) SkipZeroLength = 0; }else if (!_tcscmp(arg,TEXT("-u"))){ HideCantReadMessage = 1; + }else if (!_tcscmp(arg,TEXT("-sl"))) { + SkipLinkedDuplicates = 1; }else if (!_tcscmp(arg,TEXT("-p"))){ ShowProgress = 0; }else if (!_tcscmp(arg,TEXT("-j"))){ @@ -1145,11 +1153,13 @@ int _tmain (int argc, TCHAR **argv) // Print summary data ClearProgressInd(); + UINT64 totalBytes = ((UINT64)(DupeStats.TotalBytes / 1024) == 0 && DupeStats.TotalBytes > 0) ? 1 : DupeStats.TotalBytes / 1024; + UINT64 duplicateBytes = ((UINT64)(DupeStats.DuplicateBytes / 1024) == 0 && DupeStats.DuplicateBytes > 0) ? 1 : DupeStats.DuplicateBytes / 1024; _tprintf(TEXT("\n")); _tprintf(TEXT("Files: %8llu kBytes in %5d files\n"), - (UINT64)(DupeStats.TotalBytes/1024), DupeStats.TotalFiles); + totalBytes, DupeStats.TotalFiles); _tprintf(TEXT("Dupes: %8llu kBytes in %5d files\n"), - (UINT64)(DupeStats.DuplicateBytes/1024), DupeStats.DuplicateFiles); + duplicateBytes, DupeStats.DuplicateFiles); } if (DupeStats.ZeroLengthFiles){ _tprintf(TEXT(" %d files of zero length were skipped\n"), DupeStats.ZeroLengthFiles); diff --git a/version.h b/version.h index 5e8aa31..65fd579 100644 --- a/version.h +++ b/version.h @@ -3,7 +3,7 @@ #define STRINGIZE(s) STRINGIZE2(s) #define VERSION_MAJOR 1 -#define VERSION_MINOR 28 +#define VERSION_MINOR 30 #define VERSION_REVISION 0 #define VERSION_BUILD 0 @@ -17,7 +17,7 @@ #define VER_PRODUCT_VERSION_STR VER_FILE_VERSION_STR #define VER_ORIGINAL_FILENAME_STR VER_PRODUCTNAME_STR ".exe" #define VER_INTERNAL_NAME_STR VER_ORIGINAL_FILENAME_STR -#define VER_COPYRIGHT_STR "(C) 2017, 2020, 2022 modifications by thomas694 (@GH)" +#define VER_COPYRIGHT_STR "(C) 2017, 2020, 2022-2023 modifications by thomas694 (@GH)" #ifdef _DEBUG #define VER_VER_DEBUG VS_FF_DEBUG