Wednesday, January 17, 2007

Recursively Copying files in C#

In a project I am working on (an IIS admin interface for Boss) I need to copy all files from a Source Directory to a Destination Directory, but have the option to skip the copy if the file already exists.

I instantly thought of the SHFileOperation Shell32 Api call, and went as far as wrapping that in C#. That works fine, but either overwrites existing by default, or throws up a GUI interface asking the user if they want to overwrite. This is a web app so this wasn't an option.

I decide to roll my own, and discovered that it wasn't that hard. Worst part was recursing the directories, but I dusted off some old "C Programming 201" memories and got that sorted.

Anyway here is the code:

using System;
using System.Data;
using System.Configuration;
using System.Collections.Generic;
using System.IO;

///
/// Class that recursively copies all files in source dir to dest dir
/// Can overwrite existing or not.
///

public class DirectoryCopy
{

 private List _dirList;
 private bool _overwriteMode = false;

 public DirectoryCopy()
 {
 }

 ///
 /// Copy the Boss Files from install dir to website
 ///

 /// Path to Copy From
 /// Path to Copy To
 /// Base Path to truncate from destination path
 public void Execute(string pathFrom, string pathTo)
 {
  _dirList = new List();
  BuildFileListWithFiles(pathFrom);
  foreach (string file in _dirList)
  {
   try
   {
    string destFile = file.Replace(pathFrom, pathTo);
    CreateDirIfNotExist(Path.GetDirectoryName(destFile));
    System.IO.File.Copy(file, destFile, _overwriteMode);
   }
   catch (IOException) // if files exists then that cool just keep going
   {
    continue;
   }
  }
 }
///
/// Recursively copy files given a Source and Destination Directory.
/// Option to overwrite existing
///

/// Source Directory
/// Destination Directory
/// Overwrite if file existsts?
 public void Execute(string pathFrom, string pathTo, bool overWrite)
 {
  _overwriteMode = overWrite;
  this.Execute(pathFrom, pathTo);
 }

 private void CreateDirIfNotExist(string path)
 {
  if (!System.IO.Directory.Exists(path))
   System.IO.Directory.CreateDirectory(path);
 }

///
/// Get Sub Dirs and Files of a root directory
///

 private void BuildFileListWithFiles(string rootDir)
 {
  // Iterate through all directories
  string[] subdirectoryEntries = Directory.GetDirectories(rootDir);
  foreach (string subdirectory in subdirectoryEntries)
  {
   string[] files = Directory.GetFiles(subdirectory);
   _dirList.AddRange(files);
   BuildFileListWithFiles(subdirectory);
  }
 }
}

Apologies if the formating gets screwed.

Refactoring suggestions welcomed and encouraged.

2 comments:

Anonymous said...

the resulting program misses the files in the rootDir.

change BuildWithFiles to

///
/// Get Sub Dirs and Files of a root directory
///
private void BuildFileListWithFiles(string rootDir)
{
// get files in current directory
string[] files = Directory.GetFiles(rootDir);
_dirList.AddRange(files);
// Iterate through all directories
string[] subdirectoryEntries = Directory.GetDirectories(rootDir);
foreach (string subdirectory in subdirectoryEntries)
{
BuildFileListWithFiles(subdirectory);
}
}

will also copy all files inside the rootDir

Nice solution btw.

YesMan said...

I tried using this code, is it possible to add files from more than one directory path?

Like say for instance i have a set of files in one directory (D:\data1) and a set of files in other directory (D:\Data2) can i copy them all to a third folder
(D:\data3)? When I attempt to do this I get an error.