Moving files while preserving the folder structure I'm writing a console application that will look through a directory and move any log files that have a date modified older than X days (configurable in the app.config file).

The problem I'm having is with the Move method I wrote. It works, but I think there might be a better way to write this method and eliminate the need for the sourceRoothPath parameter. Here's what I have (it's part of a LogManager class I wrote to do the checking and moving of log files):

public void Move(string sourceRootPath, string sourcePath, string targetPath)
{
    if (String.IsNullOrWhiteSpace(sourcePath))
        throw new ArgumentNullException("sourcePath");

    if (String.IsNullOrWhiteSpace(targetPath))
        throw new ArgumentNullException("destinationPath");

    if (!File.Exists(sourcePath))
        throw new FileNotFoundException(sourcePath);

    try
    {
        // trimmedPath becomes the file path with all the subfolders, but without the
        // sourceRootPath that comes in front of it. i.e. it strips the value passed
        // in sourceRootPath from the value passed in sourcePath. The "+ 1" is to include the
        // trailing "\" in the path.
        string trimmedPath = sourcePath.Substring(sourceRootPath.Length + 1);
        string newPath = Path.Combine(targetPath, trimmedPath);
        string fileName = Path.GetFileName(sourcePath);

        // folderStructure is used for creating the subfolder structure I want to preserve.
        // (It is just removing the file name and extension from the newPath.)
        string folderStructure = newPath.Substring(0, (newPath.Length - fileName.Length));

        // Directory.CreateDirectory will create the entire folder structure for me; no need
        // for looping or recursive calls.
        Directory.CreateDirectory(folderStructure);

        // File.Move has no ability to overwrite, so I have to delete the file if it exists in the
        // destination directory so that File.Move doesn't throw an exception.
        if (File.Exists(newPath))
            File.Delete(newPath);

        File.Move(sourcePath, newPath);
        loggingService.LogInfo("Moved file from " + sourcePath + " to " + newPath + ".");
    }
    catch (Exception ex)
    {
        loggingService.LogError(ex.Message);
        throw ex;
    }
}


I included the sourceRootPath parameter because I need this method to duplicate the folder structure of the sourcePath, but I don't want it to include some of the top level folders. 

So, for example, if I'm having this application scan a log file directory at C:\someFolder\test\logs, and there are some subfolders like production\someDate or HR\HRSystem\someDate etc. I want to keep the subfolder structure in the production and HR folders, but move them to a new location like C:\test_log_archive. So C:\someFolder\test\logs\production\someDate should become C:\test_log_archive\production\someDate, and the value I would pass for sourceRootPath would be C:\someFolder\test\logs.

Does it make sense to remove the sourceRootPath and how would I do it? I feel like I should be able to accomplish this with just sourcePath and targetPath parameters, but I can't figure out a way to do it other than the code I provided above.
No, you do definitely need 3 parameters to do what you are trying to do

Although I would suggest a different 3.

public void Move(string sourceRoot, string targetRoot, string[] relative) {
    /* Precondition checks and try-catch removed for clarity */

    string source = Path.Combine(sourceRoot, relative);
    string target = Path.Combine(targetRoot, relative);
    string folderStructure = Path.GetDirectoryName(target);

    /* etc */
}


This makes clear that there is shared structure under source and target, and there isn't any direct string manipulation on file and folder names. I would even be tempted to factor this out into a seperate class, e.g.

class DirectoryMover {
    private string source;
    private string target;

    private void Move(string[] relative) { ... }
    public void MoveAll() { /* iterate over folders calling Move */ }
}