Example #1
0
        public static void Main(string[] args)
        {
            Console.WriteLine("Findup.exe v1.0 - use -help for usage information. Created in 2010 by James Gentile.");
            Console.WriteLine(" ");

            string[]           paths    = new string[0];
            System.Boolean     recurse  = false;
            System.Boolean     delete   = false;
            System.Boolean     noprompt = false;
            System.Boolean     b4b      = false;
            List <FileInfoExt> fs       = new List <FileInfoExt>();
            long   bytesInDupes         = 0;                    // bytes in all the duplicates
            long   numOfDupes           = 0;                    // number of duplicate files found.
            long   bytesRec             = 0;                    // number of bytes recovered.
            long   delFiles             = 0;                    // number of files deleted.
            int    c = 0;
            int    i = 0;
            string deleteConfirm;

            for (i = 0; i < args.Length; i++)
            {
                if ((System.String.Compare(args[i], "-help", true) == 0) || (System.String.Compare(args[i], "-h", true) == 0))
                {
                    Console.WriteLine("Usage:    findup.exe <file/directory #1> <file/directory #2> ... <file/directory #N> [-recurse] [-delete] [-noprompt]");
                    Console.WriteLine(" ");
                    Console.WriteLine("Options:  -help     - displays this help infomration.");
                    Console.WriteLine("          -recurse  - recurses through subdirectories.");
                    Console.WriteLine("          -delete   - deletes duplicates with confirmation prompt.");
                    Console.WriteLine("          -noprompt - when used with -delete option, deletes files without confirmation prompt.");
                    Console.WriteLine("          -b4b      - do a byte-for-byte comparison, instead of SHA-512 hashing. Might be much slower, but most secure.");
                    Console.WriteLine(" ");
                    Console.WriteLine("Examples: findup.exe c:\\finances -recurse");
                    Console.WriteLine("          findup.exe c:\\users\\alice\\plan.txt d:\\data -recurse -delete -noprompt");
                    Console.WriteLine("          findup.exe c:\\data .\\*.txt c:\\reports\\quarter.doc -recurse -b4b");
                    Console.WriteLine(" ");
                    return;
                }
                if (System.String.Compare(args[i], "-recurse", true) == 0)
                {
                    recurse = true;
                    continue;
                }
                if (System.String.Compare(args[i], "-delete", true) == 0)
                {
                    delete = true;
                    continue;
                }
                if (System.String.Compare(args[i], "-noprompt", true) == 0)
                {
                    noprompt = true;
                    continue;
                }
                if (System.String.Compare(args[i], "-b4b", true) == 0)
                {
                    b4b = true;
                    continue;
                }
                Array.Resize(ref paths, paths.Length + 1);
                paths[c] = args[i];
                c++;
            }

            if (paths.Length == 0)
            {
                Console.WriteLine("No files specified, try findup.exe -help");
                return;
            }

            Recurse recurseMe = new Recurse();

            recurseMe.Recursive(paths, "*.*", recurse, fs);

            if (fs.Count < 2)
            {
                Console.WriteLine("Findup.exe needs at least 2 files to compare. try findup.exe -help");
                return;
            }

            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();

            rng.GetBytes(randomNumber);                                                     // get 512-bit SHA-512 salt.

            for (i = 0; i < fs.Count; i++)
            {
                if (fs[i].Checked == true)                                                  // If file was already matched, then skip to next.
                {
                    continue;
                }

                for (c = i + 1; c < fs.Count; c++)
                {
                    if (fs[c].Checked == true)                                              // skip already matched inner loop files.
                    {
                        continue;
                    }
                    if (fs[i].FI.Length != fs[c].FI.Length)                                 // If file size matches, then check hash.
                    {
                        continue;
                    }
                    if (System.String.Compare(fs[i].FI.FullName, fs[c].FI.FullName, true) == 0) // don't count the same file as a match.
                    {
                        continue;
                    }
                    if (fs[i].SHA512_1st1K == null)                                         // check/hash first 1K first.
                    {
                        fs[i].SHA512_1st1K = Compute1KHash(fs[i].FI.FullName);
                    }
                    if (fs[c].SHA512_1st1K == null)
                    {
                        fs[c].SHA512_1st1K = Compute1KHash(fs[c].FI.FullName);
                    }
                    if (CompareHash(fs[i].SHA512_1st1K, fs[c].SHA512_1st1K) == false)                           // if the 1st 1K has the same hash..
                    {
                        continue;
                    }
                    if (fs[i].SHA512_1st1K == null)                                         // if hash error, then skip to next file.
                    {
                        continue;
                    }
                    if (b4b == true)                                                        // byte for byte comparison specified?
                    {
                        if (B4b(fs[i].FI.FullName, fs[c].FI.FullName) == false)             // call the byte for byte comparison function
                        {
                            continue;
                        }
                    }
                    else if (fs[i].FI.Length > 1024)                                        // skip hashing the file again if < 1024 bytes.
                    {
                        if (fs[i].SHA512_All == null)                                       // check/hash the rest of the files.
                        {
                            fs[i].SHA512_All = ComputeFullHash(fs[i].FI.FullName);
                        }
                        if (fs[c].SHA512_All == null)
                        {
                            fs[c].SHA512_All = ComputeFullHash(fs[c].FI.FullName);
                        }
                        if (CompareHash(fs[i].SHA512_All, fs[c].SHA512_All) == false)
                        {
                            continue;
                        }
                        if (fs[i].SHA512_All == null)                                       // check for hash fail before declaring a duplicate.
                        {
                            continue;
                        }
                    }

                    Console.WriteLine("Match  : " + fs[i].FI.FullName);
                    Console.WriteLine("with   : " + fs[c].FI.FullName);

                    fs[c].Checked = true;                                                   // do not check or match against this file again.
                    numOfDupes++;                                                           // increase count of matches.
                    bytesInDupes += fs[c].FI.Length;                                        // accumulate number of bytes in duplicates.

                    if (delete != true)                                                     // if delete is specified, try to delete the duplicate file.
                    {
                        continue;
                    }
                    if (noprompt == false)
                    {
                        Console.Write("Delete the duplicate file <Y/n>?");
                        deleteConfirm = Console.ReadLine();
                        if ((deleteConfirm[0] != 'Y') && (deleteConfirm[0] != 'y'))
                        {
                            continue;
                        }
                    }
                    try
                    {
                        File.Delete(fs[c].FI.FullName);
                        Console.WriteLine("Deleted: " + fs[c].FI.FullName);
                        bytesRec += fs[c].FI.Length;
                        delFiles++;
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("File delete error: " + e.Message);
                    }
                }
            }

            Console.WriteLine(" ");
            Console.WriteLine("Files checked      : {0:N0}", fs.Count);
            Console.WriteLine("Duplicate files    : {0:N0}", numOfDupes);
            Console.WriteLine("Duplicate bytes    : {0:N0}", bytesInDupes);
            Console.WriteLine("Duplicates deleted : {0:N0}", delFiles);
            Console.WriteLine("Recovered bytes    : {0:N0}", bytesRec);
            return;
        }