C# A folder sync tool

Hi guys!

I’ve been busy with so many developments recently. Few projects for Oracle E-Business Suite R12 & few others for learning C#. I can say I’ve “learned” how to copy, paste, correct and use it with my projects to produce beautiful results!

My recent C# projects include a WPF solution that uses WMI classes to generate hardware details for entire Windows Domain (Linux boxes are not dealt) & today I’ve decided to build a small solution that could synchronize my C# projects with our file server.

This small project can,

  • Replicate source Directory, subdirectories & files to destination folder
  • While re-ran, check whether the destination files are older than the source files and, if yes, overwrite the old ones with newer ones.

Interested to try it yourself? here comes the code

(This project uses codes copied from both MSDN & http://www.stackoverflow.com. RecursiveFileProcessor is a MSDN example, while File exists snippet was copied from stackoverflow)

using System;
using System.IO;
using System.Collections;

//http://stackoverflow.com/questions/58744/copy-the-entire-contents-of-a-directory-in-c-sharp
//

namespace RecursiveFileProcessor
{
    class Program
    {
        public static void Main(string[] args)
        {
            string sourceDirectory = @"D:\MyProjects";
            string targetDirectory = @"\\network_share_location\MyProjects";
            Copy(sourceDirectory, targetDirectory);
            Console.WriteLine();
            Console.WriteLine("Task Completed. Press any key to continue");
            Console.ReadLine();

        }

        public static void Copy(string sourceDirectory, string targetDirectory)
        {
            DirectoryInfo diSource = new DirectoryInfo(sourceDirectory);
            DirectoryInfo diTarget = new DirectoryInfo(targetDirectory);

            CopyAll(diSource, diTarget);
        }

        public static void CopyAll(DirectoryInfo source, DirectoryInfo target)
        {

            Directory.CreateDirectory(target.FullName);

            // Copy each file into the new directory.
            foreach (FileInfo fi in source.GetFiles())
            {

                DateTime created = fi.CreationTime;
                DateTime lastmodified = fi.LastWriteTime;

                if (File.Exists(Path.Combine(target.FullName, fi.Name)))
                {
                    string tFileName = Path.Combine(target.FullName, fi.Name);
                    FileInfo f2 = new FileInfo(tFileName);
                    DateTime lm = f2.LastWriteTime;
                    Console.WriteLine(@"File {0}\{1} Already Exist {2} last modified {3}", target.FullName, fi.Name, tFileName, lm);

                    try
                    {
                        if (lastmodified > lm)
                        {
                            Console.WriteLine(@"Source file {0}\{1} last modified {2} is newer than the target file {3}\{4} last modified {5}",
                                fi.DirectoryName, fi.Name, lastmodified.ToString(), target.FullName, fi.Name, lm.ToString());
                            fi.CopyTo(Path.Combine(target.FullName, fi.Name), true);
                        }
                        else
                        {
                            Console.WriteLine(@"Destination File {0}\{1} Skipped", target.FullName, fi.Name);
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }

                }
                else
                {
                    Console.WriteLine(@"Copying {0}\{1}", target.FullName, fi.Name);
                    fi.CopyTo(Path.Combine(target.FullName, fi.Name), true);
                }

            }

            // Copy each subdirectory using recursion.
            foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
            {
                DirectoryInfo nextTargetSubDir =
                    target.CreateSubdirectory(diSourceSubDir.Name);
                CopyAll(diSourceSubDir, nextTargetSubDir);
            }
        }

    }
}

Thumb rules:

  1. Do not set your source and destination folders the same.

This project uses Framework 4.5 & I am sure versions above 2.0 should support the classes referred.

If you are new to .net developments, create a project with the name “RecursiveFileProcessor”, which will let you copy and paste the whole code as it is to your project.

Do let me know whether you enjoyed your new sync toy!

regards,

rajesh

Advertisements

6 Responses to C# A folder sync tool

  1. Marhy says:

    If I delete a file in source directory, target directory is not synchronized. A deleted folder is still there : /

    • windows7bugs says:

      Hello Marhy, thanks for your feedback. Well, I overlooked that part :). Actually these are few garage projects, using which I am learning C# Coding. Please let me know whether you want to add the “real sync” features like deleting the orphaned directories at target? it will be interesting to develop

  2. Mark says:

    Here is my final implementation based on your sample, modifying the target directory to match the source directory:

    “`cs

    public static void SynchronizeDirectory(string sourceDirectory, string targetDirectory)
    {
    SynchronizeDirectory(new DirectoryInfo(sourceDirectory), new DirectoryInfo(targetDirectory));
    }

    private static void SynchronizeDirectory(DirectoryInfo source, DirectoryInfo target)
    {
    if (source.FullName == target.FullName || !source.Exists)
    {
    return;
    }
    if (!target.Exists)
    {
    Directory.CreateDirectory(target.FullName);
    }

    // Sync files. We want to keep track of files in source we’ve processed,
    // and keep a list of target files we have not seen in the process.
    var targetFilesToDelete = target.GetFiles().Select(fi => fi.Name).ToHashSet();
    foreach (FileInfo sourceFile in source.GetFiles())
    {
    if (targetFilesToDelete.Contains(sourceFile.Name)) targetFilesToDelete.Remove(sourceFile.Name);

    var targetFile = new FileInfo(Path.Combine(target.FullName, sourceFile.Name));
    if (!targetFile.Exists)
    {
    sourceFile.CopyTo(targetFile.FullName);
    }
    else if (sourceFile.LastWriteTime > targetFile.LastWriteTime)
    {
    sourceFile.CopyTo(targetFile.FullName, true);
    }
    }
    foreach (var file in targetFilesToDelete)
    {
    File.Delete(Path.Combine(target.FullName, file));
    }

    // Sync folders.
    var targetSubDirsToDelete = target.GetDirectories().Select(fi => fi.Name).ToHashSet();
    foreach (DirectoryInfo sourceSubDir in source.GetDirectories())
    {
    if (targetSubDirsToDelete.Contains(sourceSubDir.Name)) targetSubDirsToDelete.Remove(sourceSubDir.Name);
    DirectoryInfo targetSubDir = new DirectoryInfo(Path.Combine(target.FullName, sourceSubDir.Name));
    SynchronizeDirectory(sourceSubDir, targetSubDir);
    }
    foreach (var subdir in targetSubDirsToDelete)
    {
    DeleteDirectory(Path.Combine(target.FullName, subdir), true);
    }
    }
    “`

    Tested and running in production.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.