views:

77

answers:

5

I need a procedure that checks if new folders/files were added to a given selected folder. I need this procedure to run upon application start up so the processing time at this stage is important.

I guess I can make a log of current state, log of the previous state, sort and compare them.

  1. First I need to know if there is another way.

  2. Second if there is no other way what is the best way to find difference between two lists of files paths: both structure and algorithms.

Old state:

c:\firstfolder\a.doc
c:\firstfolder\b.doc
c:\firstfolder\secondFolder\a.doc
c:\firstfolder\secondFolder\b.doc

New state:

c:\firstfolder\a.doc
c:\firstfolder\b.doc 
c:\firstfolder\secondFolder\a.doc 
c:\firstfolder\secondFolder\b.doc 
c:\firstfolder\secondFolder\c.doc

I'm looking for c:\firstfolder\secondFolder\c.doc.

A: 

Since your application is not running continuously, using a FileSystemWatcher does not seem like a good option for you, but I did want to mention it since it might spark some ideas on your side.

If you have a list of the old state and create a list of the new state you can use an algorithm like the one outlined here to compare the two lists to determine additions and deletions since the first list was created. That accepted answer to the provided link also has a nice solution that works very well if the lists are not sorted.

Chris Taylor
The HashSets looks promising but I don't know anything about them... Will try try to learn more about them. Thanks
Asaf
+1  A: 

You can use the FileSystemWatcher class, I think it's doing exactly what you are after.

CyberDude
That only works when the application is running. It won't detect changes that occur between invocations of the program.
ChrisF
+1 @CyberDude: thanks, it's good to know that this listener exists, (it made me wonder if I need it as well) yet as ChrisF said it only catch changes during runtime, and I need to know what has changes since the previous run of the application
Asaf
A: 

I think the best bet is recursing through the directory and saving the state. Something like this:

public List<FileData> RecurseDirectory(string directory, int level, out int files, out int folders)
        {
            IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
            //long size = 0;
            files = 0;
            folders = 0;
            WIN32_FIND_DATA findData;
            List<FileData> list = new List<FileData>();

            IntPtr findHandle;

            // add global escape chars if not present.
            if (directory.StartsWith(@"\\?\"))
            {
                findHandle = FindFirstFile(directory + @"\*", out findData);
            }
            else
            {
                findHandle = FindFirstFile(@"\\?\" + directory + @"\*", out findData);
            }


            if (findHandle != INVALID_HANDLE_VALUE)
            {
                //if file exists:


                do
                {
                    if ((findData.dwFileAttributes & FileAttributes.Directory) != 0)
                    {
                        //if it's a directory:

                        if (findData.cFileName != "." && findData.cFileName != "..")
                        {
                            //increment folder counter.
                            folders++;

                            int subfiles, subfolders;
                            string subdirectory = directory + (directory.EndsWith(@"\") ? "" : @"\") +
                                findData.cFileName;
                            //Console.WriteLine("Dir:" + subdirectory);

                            //add it to list
                            String path = subdirectory;
                            FileData tempFileData = new FileData();
                            tempFileData.path = path;
                            tempFileData.fileProperties = findData;
                            list.Add(tempFileData);

                            //allows -1 to do complete search.
                            if (level != 0)
                            {
                                //recurse through to next subfolder
                                list.AddRange(RecurseDirectory(subdirectory, level - 1, out subfiles, out subfolders));

                                folders += subfolders;
                                files += subfiles;
                            }
                        }
                    }
                    else
                    {
                        // File
                        files++;
                        string subfile = directory + (directory.EndsWith(@"\") ? "" : @"\") +
                                findData.cFileName;
                        //Console.WriteLine("File:" + subfile);
                        //list.Add("File:" + subfile);
                        String path = subfile;
                        FileData t = new FileData();
                        t.path = path;
                        t.fileProperties = findData;
                        list.Add(t);

                        //size += (long)findData.nFileSizeLow + (long)findData.nFileSizeHigh * 4294967296L;
                    }
                }
                while (FindNextFile(findHandle, out findData));
                FindClose(findHandle);

            }

            return list;
        }

After this, you'll have the list of the state. If you have the old-state in the list also. Compare the lists Now.

lalli
No need for all the recursion, Directory.GetDirectories and in Framework 4.0 Directory.EnumerateDirectories can traverse the entire tree in a single call. Not to mention that the above code would also require additional P/Invoke declarations, that are not shown.
Chris Taylor
A: 

You can save time info of the last state. Then you just can compare the creation times of files and folders with that. The following code may give you an idea:

foreach(FileInfo f in dir.GetFiles() {
   if(f.CreationTime > dtLastState ) {
         //do some interesting stuff
   }
} 

Edit: This is not a complete answer. You cannot get the deleted files by this code.

Zafer
+2  A: 

I think that the Sync Framework may be what you are looking for.

http://msdn.microsoft.com/en-us/sync/default.aspx

John Gietzen
I need to compare two folders that have the same sub folders but the files are equal only by name... they are created separately so their content, size and other parameters are not equal to the source folder. That is the reason I don't think your solution will work for me this time. Thanks Asaf
Asaf